mirror of
https://github.com/github/codeql.git
synced 2026-06-23 13:47:03 +02:00
Compare commits
1 Commits
copilot/up
...
python/cla
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7126b95b16 |
@@ -2,7 +2,7 @@
|
|||||||
* @github/code-scanning-alert-coverage
|
* @github/code-scanning-alert-coverage
|
||||||
|
|
||||||
# CodeQL language libraries
|
# CodeQL language libraries
|
||||||
/actions/ @github/code-scanning-alert-coverage
|
/actions/ @github/codeql-dynamic
|
||||||
/cpp/ @github/codeql-c-analysis
|
/cpp/ @github/codeql-c-analysis
|
||||||
/csharp/ @github/codeql-csharp
|
/csharp/ @github/codeql-csharp
|
||||||
/csharp/autobuilder/Semmle.Autobuild.Cpp @github/codeql-c-extractor @github/code-scanning-language-coverage
|
/csharp/autobuilder/Semmle.Autobuild.Cpp @github/codeql-c-extractor @github/code-scanning-language-coverage
|
||||||
@@ -59,5 +59,9 @@ MODULE.bazel @github/codeql-ci-reviewers
|
|||||||
/.github/workflows/rust.yml @github/codeql-rust
|
/.github/workflows/rust.yml @github/codeql-rust
|
||||||
/.github/workflows/swift.yml @github/codeql-swift
|
/.github/workflows/swift.yml @github/codeql-swift
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
/misc/scripts/accept-expected-changes-from-ci.py @RasmusWL
|
||||||
|
/misc/scripts/generate-code-scanning-query-list.py @RasmusWL
|
||||||
|
|
||||||
# .devcontainer
|
# .devcontainer
|
||||||
/.devcontainer/ @github/codeql-ci-reviewers
|
/.devcontainer/ @github/codeql-ci-reviewers
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
### Minor Analysis Improvements
|
### Minor Analysis Improvements
|
||||||
|
|
||||||
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, including regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a SHA-1 or SHA-256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, include regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a sha1 or sha256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
||||||
|
|
||||||
## 0.4.36
|
## 0.4.36
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
category: fix
|
|
||||||
---
|
|
||||||
* The query `actions/pr-on-self-hosted-runner` was updated to the latest standard runner labels reducing false positive results.
|
|
||||||
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
### Minor Analysis Improvements
|
### Minor Analysis Improvements
|
||||||
|
|
||||||
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, including regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a SHA-1 or SHA-256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
* The GitHub Actions analysis now recognizes more Bash regex checks that restrict a value to alphanumeric characters, include regexes like `^[0-9a-zA-Z]{40}([0-9a-zA-Z]{24})?$` which check for a sha1 or sha256 hash. This may reduce false positive results where command output is validated with grouped or optional alphanumeric patterns before being used.
|
||||||
|
|||||||
@@ -1920,5 +1920,3 @@ private YamlMappingLikeNode resolveMatrixAccessPath(
|
|||||||
else result = resolveMatrixAccessPath(newRoot, rest)
|
else result = resolveMatrixAccessPath(newRoot, rest)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Comment = YamlComment;
|
|
||||||
|
|||||||
@@ -52,12 +52,6 @@ private module YamlSig implements LibYaml::InputSig {
|
|||||||
class ParseErrorBase extends LocatableBase, @yaml_error {
|
class ParseErrorBase extends LocatableBase, @yaml_error {
|
||||||
string getMessage() { yaml_errors(this, result) }
|
string getMessage() { yaml_errors(this, result) }
|
||||||
}
|
}
|
||||||
|
|
||||||
class CommentBase extends LocatableBase, @yaml_comment {
|
|
||||||
string getText() { yaml_comments(this, result, _) }
|
|
||||||
|
|
||||||
override string toString() { yaml_comments(this, _, result) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
import LibYaml::Make<YamlSig>
|
import LibYaml::Make<YamlSig>
|
||||||
|
|||||||
@@ -2,12 +2,10 @@ import actions
|
|||||||
|
|
||||||
bindingset[runner]
|
bindingset[runner]
|
||||||
predicate isGithubHostedRunner(string runner) {
|
predicate isGithubHostedRunner(string runner) {
|
||||||
// The list of github hosted repos:
|
// list of github hosted repos: https://github.com/actions/runner-images/blob/main/README.md#available-images
|
||||||
// https://github.com/actions/runner-images/blob/main/README.md#available-images
|
runner
|
||||||
// https://docs.github.com/en/enterprise-cloud@latest/actions/how-tos/write-workflows/choose-where-workflows-run/choose-the-runner-for-a-job#standard-github-hosted-runners-for-public-repositories
|
.toLowerCase()
|
||||||
runner.toLowerCase().regexpMatch("^ubuntu-([0-9.]+|latest|slim)(-arm)?$") or
|
.regexpMatch("^(ubuntu-([0-9.]+|latest)|macos-([0-9]+|latest)(-x?large)?|windows-([0-9.]+|latest))$")
|
||||||
runner.toLowerCase().regexpMatch("^macos-([0-9]+|latest)(-x?large|-intel)?$") or
|
|
||||||
runner.toLowerCase().regexpMatch("^windows-([0-9.]+|latest)(-vs[0-9.]+)?(-arm)?$")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[runner]
|
bindingset[runner]
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on a minor point, added one more listed resource and added one more recommendation for things to check.
|
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on in minor point, added one more listed resource and added one more recommendation for things to check.
|
||||||
|
|
||||||
## 0.6.28
|
## 0.6.28
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @name Checkout of untrusted code in a non-privileged context
|
* @name Checkout of untrusted code in a trusted context
|
||||||
* @description Checking out and running the build script from a fork executes untrusted code. Even in a
|
* @description Privileged workflows have read/write access to the base repository and access to secrets.
|
||||||
* non-privileged workflow, this can be abused, for example to compromise self-hosted runners
|
* By explicitly checking out and running the build script from a fork the untrusted code is running in an environment
|
||||||
* or to poison caches and artifacts that are later consumed by privileged workflows.
|
* that is able to push to the base repository and to access secrets.
|
||||||
* @kind problem
|
* @kind problem
|
||||||
* @problem.severity warning
|
* @problem.severity warning
|
||||||
* @precision medium
|
* @precision medium
|
||||||
@@ -20,4 +20,4 @@ from PRHeadCheckoutStep checkout
|
|||||||
where
|
where
|
||||||
// the checkout occurs in a non-privileged context
|
// the checkout occurs in a non-privileged context
|
||||||
inNonPrivilegedContext(checkout)
|
inNonPrivilegedContext(checkout)
|
||||||
select checkout, "Potential unsafe checkout of untrusted pull request on non-privileged workflow."
|
select checkout, "Potential unsafe checkout of untrusted pull request on privileged workflow."
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
category: queryMetadata
|
|
||||||
---
|
|
||||||
* The name, description, and alert message of `actions/untrusted-checkout/medium` have been corrected to describe a non-privileged context.
|
|
||||||
@@ -15,4 +15,4 @@
|
|||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on a minor point, added one more listed resource and added one more recommendation for things to check.
|
* Adjusted (minor) help file descriptions for queries: `actions/untrusted-checkout/critical`, `actions/untrusted-checkout/high`, `actions/untrusted-checkout/medium`. Clarified wording on in minor point, added one more listed resource and added one more recommendation for things to check.
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
name: test
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os:
|
|
||||||
- ubuntu-latest
|
|
||||||
- ubuntu-24.04
|
|
||||||
- ubuntu-24.04-arm
|
|
||||||
- ubuntu-22.04
|
|
||||||
- ubuntu-22.04-arm
|
|
||||||
- ubuntu-26.04
|
|
||||||
- ubuntu-26.04-arm
|
|
||||||
- ubuntu-slim
|
|
||||||
- macos-26
|
|
||||||
- macos-26-xlarge
|
|
||||||
- macos-26-intel
|
|
||||||
- macos-26-large
|
|
||||||
- macos-latest-large
|
|
||||||
- macos-15-large
|
|
||||||
- macos-15
|
|
||||||
- macos-15-intel
|
|
||||||
- macos-latest
|
|
||||||
- macos-15
|
|
||||||
- macos-15-xlarge
|
|
||||||
- macos-14-large
|
|
||||||
- macos-14
|
|
||||||
- macos-14-xlarge
|
|
||||||
- windows-2025-vs2026
|
|
||||||
- windows-latest
|
|
||||||
- windows-2025
|
|
||||||
- windows-2022
|
|
||||||
- windows-11
|
|
||||||
- windows-11-arm
|
|
||||||
- windows-11-vs2026-arm
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- run: cmd
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
| .github/workflows/artifactpoisoning81.yml:11:9:14:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
| .github/workflows/artifactpoisoning81.yml:11:9:14:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||||
| .github/workflows/dependabot2.yml:33:9:38:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
| .github/workflows/dependabot2.yml:33:9:38:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||||
| .github/workflows/mend.yml:22:9:29:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
| .github/workflows/mend.yml:22:9:29:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||||
| .github/workflows/poc3.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
| .github/workflows/poc3.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||||
| .github/workflows/poc.yml:30:9:36:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
| .github/workflows/poc.yml:30:9:36:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||||
| .github/workflows/priv_pull_request_checkout.yml:14:9:20:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
| .github/workflows/priv_pull_request_checkout.yml:14:9:20:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||||
| .github/workflows/test3.yml:28:9:33:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
| .github/workflows/test3.yml:28:9:33:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||||
| .github/workflows/test4.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
| .github/workflows/test4.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||||
| .github/workflows/test8.yml:20:9:26:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
| .github/workflows/test8.yml:20:9:26:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||||
| .github/workflows/test9.yml:11:9:16:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
| .github/workflows/test9.yml:11:9:16:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
|||||||
description: Fix NameQualifier inconsistency
|
|
||||||
compatibility: full
|
|
||||||
@@ -1071,7 +1071,7 @@ class NullPointerType extends BuiltInType {
|
|||||||
* const float fa[40];
|
* const float fa[40];
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class DerivedType extends Type, NameQualifyingElement, @derivedtype {
|
class DerivedType extends Type, @derivedtype {
|
||||||
override string toString() { result = this.getName() }
|
override string toString() { result = this.getName() }
|
||||||
|
|
||||||
override string getName() { derivedtypes(underlyingElement(this), result, _, _) }
|
override string getName() { derivedtypes(underlyingElement(this), result, _, _) }
|
||||||
|
|||||||
@@ -1430,8 +1430,7 @@ specialnamequalifyingelements(
|
|||||||
@namequalifyingelement = @namespace
|
@namequalifyingelement = @namespace
|
||||||
| @specialnamequalifyingelement
|
| @specialnamequalifyingelement
|
||||||
| @usertype
|
| @usertype
|
||||||
| @decltype
|
| @decltype;
|
||||||
| @derivedtype;
|
|
||||||
|
|
||||||
namequalifiers(
|
namequalifiers(
|
||||||
unique int id: @namequalifier,
|
unique int id: @namequalifier,
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
|||||||
description: Fix NameQualifier inconsistency
|
|
||||||
compatibility: full
|
|
||||||
@@ -1,7 +1,3 @@
|
|||||||
| inconsistency2.cpp:3:3:3:5 | T:: | inconsistency2.cpp:3:3:3:6 | x | inconsistency2.cpp:2:20:2:20 | T |
|
|
||||||
| inconsistency2.cpp:3:3:3:11 | const s:: | inconsistency2.cpp:3:3:3:6 | x | file://:0:0:0:0 | const s |
|
|
||||||
| inconsistency.cpp:7:20:7:22 | S:: | inconsistency.cpp:7:20:7:23 | (int)... | inconsistency.cpp:4:8:4:8 | S |
|
|
||||||
| inconsistency.cpp:7:20:7:22 | S:: | inconsistency.cpp:7:20:7:23 | A | inconsistency.cpp:4:8:4:8 | S |
|
|
||||||
| name_qualifiers.cpp:29:7:29:8 | :: | name_qualifiers.cpp:29:7:29:9 | x | file://:0:0:0:0 | (global namespace) |
|
| name_qualifiers.cpp:29:7:29:8 | :: | name_qualifiers.cpp:29:7:29:9 | x | file://:0:0:0:0 | (global namespace) |
|
||||||
| name_qualifiers.cpp:31:7:31:10 | N1:: | name_qualifiers.cpp:31:7:31:12 | nx | name_qualifiers.cpp:4:11:4:12 | N1 |
|
| name_qualifiers.cpp:31:7:31:10 | N1:: | name_qualifiers.cpp:31:7:31:12 | nx | name_qualifiers.cpp:4:11:4:12 | N1 |
|
||||||
| name_qualifiers.cpp:34:7:34:8 | :: | name_qualifiers.cpp:34:9:34:12 | N1:: | file://:0:0:0:0 | (global namespace) |
|
| name_qualifiers.cpp:34:7:34:8 | :: | name_qualifiers.cpp:34:9:34:12 | N1:: | file://:0:0:0:0 | (global namespace) |
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import cpp
|
import cpp
|
||||||
|
|
||||||
from NameQualifier nq, Location l
|
from NameQualifier nq, Location l
|
||||||
where l = nq.getQualifiedElement().getLocation()
|
where
|
||||||
|
l = nq.getQualifiedElement().getLocation() and
|
||||||
|
l.getFile().getShortName() = "name_qualifiers"
|
||||||
select nq, nq.getQualifiedElement(), nq.getQualifyingElement()
|
select nq, nq.getQualifiedElement(), nq.getQualifyingElement()
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
// This file is present to test whether name-qualifying an enum constant leads to a database inconsistency.
|
// This file is present to test whether name-qualifying an enum constant leads to a database inconsistency.
|
||||||
|
// As such, there is no QL part of the test.
|
||||||
|
|
||||||
struct S { enum E { A }; };
|
struct S { enum E { A }; };
|
||||||
|
|
||||||
static void f() {
|
static int f() {
|
||||||
switch(0) { case S::A: break; }
|
switch(0) { case S::A: break; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
namespace {
|
|
||||||
template <typename T> T f() {
|
|
||||||
T::x;
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
struct s {
|
|
||||||
static int x;
|
|
||||||
};
|
|
||||||
struct t {
|
|
||||||
s x = f<const s>();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -135,7 +135,7 @@ namespace Semmle.Autobuild.CSharp.Tests
|
|||||||
if (!EnumerateFiles.TryGetValue(dir, out var str))
|
if (!EnumerateFiles.TryGetValue(dir, out var str))
|
||||||
throw new ArgumentException("Missing EnumerateFiles " + dir);
|
throw new ArgumentException("Missing EnumerateFiles " + dir);
|
||||||
|
|
||||||
return str.Split("\n").Select(p => PathJoin(dir, p));
|
return str.Split("\n").Select(p => PathCombine(dir, p));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDictionary<string, string> EnumerateDirectories { get; } = new Dictionary<string, string>();
|
public IDictionary<string, string> EnumerateDirectories { get; } = new Dictionary<string, string>();
|
||||||
@@ -147,7 +147,7 @@ namespace Semmle.Autobuild.CSharp.Tests
|
|||||||
|
|
||||||
return string.IsNullOrEmpty(str)
|
return string.IsNullOrEmpty(str)
|
||||||
? Enumerable.Empty<string>()
|
? Enumerable.Empty<string>()
|
||||||
: str.Split("\n").Select(p => PathJoin(dir, p));
|
: str.Split("\n").Select(p => PathCombine(dir, p));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsWindows { get; set; }
|
public bool IsWindows { get; set; }
|
||||||
@@ -170,7 +170,7 @@ namespace Semmle.Autobuild.CSharp.Tests
|
|||||||
|
|
||||||
bool IBuildActions.IsMonoInstalled() => IsMonoInstalled;
|
bool IBuildActions.IsMonoInstalled() => IsMonoInstalled;
|
||||||
|
|
||||||
public string PathJoin(params string[] parts)
|
public string PathCombine(params string[] parts)
|
||||||
{
|
{
|
||||||
return string.Join(IsWindows ? '\\' : '/', parts.Where(p => !string.IsNullOrWhiteSpace(p)));
|
return string.Join(IsWindows ? '\\' : '/', parts.Where(p => !string.IsNullOrWhiteSpace(p)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ namespace Semmle.Autobuild.CSharp
|
|||||||
=> WithDotNet(builder, ensureDotNetAvailable: false, (_, env) => f(env));
|
=> WithDotNet(builder, ensureDotNetAvailable: false, (_, env) => f(env));
|
||||||
|
|
||||||
private static string DotNetCommand(IBuildActions actions, string? dotNetPath) =>
|
private static string DotNetCommand(IBuildActions actions, string? dotNetPath) =>
|
||||||
dotNetPath is not null ? actions.PathJoin(dotNetPath, "dotnet") : "dotnet";
|
dotNetPath is not null ? actions.PathCombine(dotNetPath, "dotnet") : "dotnet";
|
||||||
|
|
||||||
private static CommandBuilder GetCleanCommand(IBuildActions actions, string? dotNetPath, IDictionary<string, string>? environment)
|
private static CommandBuilder GetCleanCommand(IBuildActions actions, string? dotNetPath, IDictionary<string, string>? environment)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ namespace Semmle.Autobuild.Cpp.Tests
|
|||||||
|
|
||||||
bool IBuildActions.IsMonoInstalled() => IsMonoInstalled;
|
bool IBuildActions.IsMonoInstalled() => IsMonoInstalled;
|
||||||
|
|
||||||
string IBuildActions.PathJoin(params string[] parts)
|
string IBuildActions.PathCombine(params string[] parts)
|
||||||
{
|
{
|
||||||
return string.Join(IsWindows ? '\\' : '/', parts.Where(p => !string.IsNullOrWhiteSpace(p)));
|
return string.Join(IsWindows ? '\\' : '/', parts.Where(p => !string.IsNullOrWhiteSpace(p)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ namespace Semmle.Autobuild.Shared
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">The relative path.</param>
|
/// <param name="path">The relative path.</param>
|
||||||
/// <returns>True iff the path was found.</returns>
|
/// <returns>True iff the path was found.</returns>
|
||||||
public bool HasRelativePath(string path) => HasPath(Actions.PathJoin(RootDirectory, path));
|
public bool HasRelativePath(string path) => HasPath(Actions.PathCombine(RootDirectory, path));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// List of project/solution files to build.
|
/// List of project/solution files to build.
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace Semmle.Autobuild.Shared
|
|||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
// Attempt to use vswhere to find installations of Visual Studio
|
// Attempt to use vswhere to find installations of Visual Studio
|
||||||
var vswhere = actions.PathJoin(programFilesx86, "Microsoft Visual Studio", "Installer", "vswhere.exe");
|
var vswhere = actions.PathCombine(programFilesx86, "Microsoft Visual Studio", "Installer", "vswhere.exe");
|
||||||
|
|
||||||
if (actions.FileExists(vswhere))
|
if (actions.FileExists(vswhere))
|
||||||
{
|
{
|
||||||
@@ -51,14 +51,14 @@ namespace Semmle.Autobuild.Shared
|
|||||||
if (majorVersion < 15)
|
if (majorVersion < 15)
|
||||||
{
|
{
|
||||||
// Visual Studio 2015 and below
|
// Visual Studio 2015 and below
|
||||||
yield return new VcVarsBatFile(actions.PathJoin(vsInstallation.InstallationPath, @"VC\vcvarsall.bat"), majorVersion);
|
yield return new VcVarsBatFile(actions.PathCombine(vsInstallation.InstallationPath, @"VC\vcvarsall.bat"), majorVersion);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Visual Studio 2017 and above
|
// Visual Studio 2017 and above
|
||||||
yield return new VcVarsBatFile(actions.PathJoin(vsInstallation.InstallationPath, @"VC\Auxiliary\Build\vcvars32.bat"), majorVersion);
|
yield return new VcVarsBatFile(actions.PathCombine(vsInstallation.InstallationPath, @"VC\Auxiliary\Build\vcvars32.bat"), majorVersion);
|
||||||
yield return new VcVarsBatFile(actions.PathJoin(vsInstallation.InstallationPath, @"VC\Auxiliary\Build\vcvars64.bat"), majorVersion);
|
yield return new VcVarsBatFile(actions.PathCombine(vsInstallation.InstallationPath, @"VC\Auxiliary\Build\vcvars64.bat"), majorVersion);
|
||||||
yield return new VcVarsBatFile(actions.PathJoin(vsInstallation.InstallationPath, @"Common7\Tools\VsDevCmd.bat"), majorVersion);
|
yield return new VcVarsBatFile(actions.PathCombine(vsInstallation.InstallationPath, @"Common7\Tools\VsDevCmd.bat"), majorVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// else: Skip installation without a version
|
// else: Skip installation without a version
|
||||||
@@ -68,10 +68,10 @@ namespace Semmle.Autobuild.Shared
|
|||||||
}
|
}
|
||||||
|
|
||||||
// vswhere not installed or didn't run correctly - return legacy Visual Studio versions
|
// vswhere not installed or didn't run correctly - return legacy Visual Studio versions
|
||||||
yield return new VcVarsBatFile(actions.PathJoin(programFilesx86, @"Microsoft Visual Studio 14.0\VC\vcvarsall.bat"), 14);
|
yield return new VcVarsBatFile(actions.PathCombine(programFilesx86, @"Microsoft Visual Studio 14.0\VC\vcvarsall.bat"), 14);
|
||||||
yield return new VcVarsBatFile(actions.PathJoin(programFilesx86, @"Microsoft Visual Studio 12.0\VC\vcvarsall.bat"), 12);
|
yield return new VcVarsBatFile(actions.PathCombine(programFilesx86, @"Microsoft Visual Studio 12.0\VC\vcvarsall.bat"), 12);
|
||||||
yield return new VcVarsBatFile(actions.PathJoin(programFilesx86, @"Microsoft Visual Studio 11.0\VC\vcvarsall.bat"), 11);
|
yield return new VcVarsBatFile(actions.PathCombine(programFilesx86, @"Microsoft Visual Studio 11.0\VC\vcvarsall.bat"), 11);
|
||||||
yield return new VcVarsBatFile(actions.PathJoin(programFilesx86, @"Microsoft Visual Studio 10.0\VC\vcvarsall.bat"), 10);
|
yield return new VcVarsBatFile(actions.PathCombine(programFilesx86, @"Microsoft Visual Studio 10.0\VC\vcvarsall.bat"), 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ namespace Semmle.Autobuild.Shared
|
|||||||
// Use `nuget.exe` from source code repo, if present, otherwise first attempt with global
|
// Use `nuget.exe` from source code repo, if present, otherwise first attempt with global
|
||||||
// `nuget` command, and if that fails, attempt to download `nuget.exe` from nuget.org
|
// `nuget` command, and if that fails, attempt to download `nuget.exe` from nuget.org
|
||||||
var nuget = builder.GetFilename("nuget.exe").Select(t => t.Item1).FirstOrDefault() ?? "nuget";
|
var nuget = builder.GetFilename("nuget.exe").Select(t => t.Item1).FirstOrDefault() ?? "nuget";
|
||||||
var nugetDownloadPath = builder.Actions.PathJoin(FileUtils.GetTemporaryWorkingDirectory(builder.Actions.GetEnvironmentVariable, builder.Options.Language.UpperCaseName, out _), ".nuget", "nuget.exe");
|
var nugetDownloadPath = builder.Actions.PathCombine(FileUtils.GetTemporaryWorkingDirectory(builder.Actions.GetEnvironmentVariable, builder.Options.Language.UpperCaseName, out _), ".nuget", "nuget.exe");
|
||||||
var nugetDownloaded = false;
|
var nugetDownloaded = false;
|
||||||
|
|
||||||
var ret = BuildScript.Success;
|
var ret = BuildScript.Success;
|
||||||
|
|||||||
@@ -107,9 +107,8 @@ namespace Semmle.Autobuild.Shared
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var includePath = builder.Actions.PathJoin(include.Value.Split('\\', StringSplitOptions.RemoveEmptyEntries));
|
var includePath = builder.Actions.PathCombine(include.Value.Split('\\', StringSplitOptions.RemoveEmptyEntries));
|
||||||
var path = Path.IsPathRooted(includePath) ? includePath : builder.Actions.PathJoin(DirectoryName, includePath);
|
ret.Add(new Project<TAutobuildOptions>(builder, builder.Actions.PathCombine(DirectoryName, includePath)));
|
||||||
ret.Add(new Project<TAutobuildOptions>(builder, path));
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ namespace Semmle.Autobuild.Shared
|
|||||||
|
|
||||||
includedProjects = solution.ProjectsInOrder
|
includedProjects = solution.ProjectsInOrder
|
||||||
.Where(p => p.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat)
|
.Where(p => p.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat)
|
||||||
.Select(p => builder.Actions.PathJoin(DirectoryName, builder.Actions.PathJoin(p.RelativePath.Split('\\', StringSplitOptions.RemoveEmptyEntries))))
|
.Select(p => builder.Actions.PathCombine(DirectoryName, builder.Actions.PathCombine(p.RelativePath.Split('\\', StringSplitOptions.RemoveEmptyEntries))))
|
||||||
.Select(p => new Project<TAutobuildOptions>(builder, p))
|
.Select(p => new Project<TAutobuildOptions>(builder, p))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
|||||||
description: Restructure and rename types related to operations.
|
|
||||||
compatibility: full
|
|
||||||
@@ -50,7 +50,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var path = Path.Join(p, ParseFilePath(d));
|
var path = Path.Combine(p, ParseFilePath(d));
|
||||||
Paths.Add(path);
|
Paths.Add(path);
|
||||||
Packages.Add(GetPackageName(p));
|
Packages.Add(GetPackageName(p));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.diagnosticsWriter = new DiagnosticsStream(Path.Join(
|
this.diagnosticsWriter = new DiagnosticsStream(Path.Combine(
|
||||||
diagDirEnv ?? "",
|
diagDirEnv ?? "",
|
||||||
$"dependency-manager-{DateTime.UtcNow:yyyyMMddHHmm}-{Environment.ProcessId}.jsonc"));
|
$"dependency-manager-{DateTime.UtcNow:yyyyMMddHHmm}-{Environment.ProcessId}.jsonc"));
|
||||||
this.sourceDir = new DirectoryInfo(srcDir);
|
this.sourceDir = new DirectoryInfo(srcDir);
|
||||||
@@ -327,7 +327,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
private void RemoveNugetPackageReference(string packagePrefix, ISet<AssemblyLookupLocation> dllLocations)
|
private void RemoveNugetPackageReference(string packagePrefix, ISet<AssemblyLookupLocation> dllLocations)
|
||||||
{
|
{
|
||||||
var packageFolder = nugetPackageRestorer.PackageDirectory.DirInfo.FullName.ToLowerInvariant();
|
var packageFolder = nugetPackageRestorer.PackageDirectory.DirInfo.FullName.ToLowerInvariant();
|
||||||
var packagePathPrefix = Path.Join(packageFolder, packagePrefix.ToLowerInvariant());
|
var packagePathPrefix = Path.Combine(packageFolder, packagePrefix.ToLowerInvariant());
|
||||||
var toRemove = dllLocations.Where(s => s.Path.StartsWith(packagePathPrefix, StringComparison.InvariantCultureIgnoreCase));
|
var toRemove = dllLocations.Where(s => s.Path.StartsWith(packagePathPrefix, StringComparison.InvariantCultureIgnoreCase));
|
||||||
foreach (var path in toRemove)
|
foreach (var path in toRemove)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DotNet(ILogger logger, string? dotNetPath, TemporaryDirectory tempWorkingDirectory, DependabotProxy? dependabotProxy) : this(new DotNetCliInvoker(logger, Path.Join(dotNetPath ?? string.Empty, "dotnet"), dependabotProxy), logger, dotNetPath is null, tempWorkingDirectory) { }
|
private DotNet(ILogger logger, string? dotNetPath, TemporaryDirectory tempWorkingDirectory, DependabotProxy? dependabotProxy) : this(new DotNetCliInvoker(logger, Path.Combine(dotNetPath ?? string.Empty, "dotnet"), dependabotProxy), logger, dotNetPath is null, tempWorkingDirectory) { }
|
||||||
|
|
||||||
internal static IDotNet Make(IDotNetCliInvoker dotnetCliInvoker, ILogger logger, bool runDotnetInfo) => new DotNet(dotnetCliInvoker, logger, runDotnetInfo);
|
internal static IDotNet Make(IDotNetCliInvoker dotnetCliInvoker, ILogger logger, bool runDotnetInfo) => new DotNet(dotnetCliInvoker, logger, runDotnetInfo);
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
var path = ".empty";
|
var path = ".empty";
|
||||||
if (tempWorkingDirectory != null)
|
if (tempWorkingDirectory != null)
|
||||||
{
|
{
|
||||||
path = Path.Join(tempWorkingDirectory.ToString(), "emptyFakeDotnetRoot");
|
path = Path.Combine(tempWorkingDirectory.ToString(), "emptyFakeDotnetRoot");
|
||||||
Directory.CreateDirectory(path);
|
Directory.CreateDirectory(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,7 +303,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var dotnetInstallPath = actions.PathJoin(tempWorkingDirectory, ".dotnet", "dotnet-install.sh");
|
var dotnetInstallPath = actions.PathCombine(tempWorkingDirectory, ".dotnet", "dotnet-install.sh");
|
||||||
var downloadDotNetInstallSh = BuildScript.DownloadFile(
|
var downloadDotNetInstallSh = BuildScript.DownloadFile(
|
||||||
"https://dot.net/v1/dotnet-install.sh",
|
"https://dot.net/v1/dotnet-install.sh",
|
||||||
dotnetInstallPath,
|
dotnetInstallPath,
|
||||||
@@ -339,7 +339,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var dotnetInfo = InfoScript(actions, actions.PathJoin(path, "dotnet"), MinimalEnvironment.ToDictionary(), logger);
|
var dotnetInfo = InfoScript(actions, actions.PathCombine(path, "dotnet"), MinimalEnvironment.ToDictionary(), logger);
|
||||||
|
|
||||||
Func<string, BuildScript> getInstallAndVerify = version =>
|
Func<string, BuildScript> getInstallAndVerify = version =>
|
||||||
// run `dotnet --info` after install, to check that it executes successfully
|
// run `dotnet --info` after install, to check that it executes successfully
|
||||||
@@ -384,7 +384,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static BuildScript WithDotNet(IBuildActions actions, ILogger logger, IEnumerable<string> files, string tempWorkingDirectory, bool shouldCleanUp, bool ensureDotNetAvailable, string? version, Func<string?, BuildScript> f)
|
public static BuildScript WithDotNet(IBuildActions actions, ILogger logger, IEnumerable<string> files, string tempWorkingDirectory, bool shouldCleanUp, bool ensureDotNetAvailable, string? version, Func<string?, BuildScript> f)
|
||||||
{
|
{
|
||||||
var installDir = actions.PathJoin(tempWorkingDirectory, ".dotnet");
|
var installDir = actions.PathCombine(tempWorkingDirectory, ".dotnet");
|
||||||
var installScript = DownloadDotNet(actions, logger, files, tempWorkingDirectory, shouldCleanUp, installDir, version, ensureDotNetAvailable);
|
var installScript = DownloadDotNet(actions, logger, files, tempWorkingDirectory, shouldCleanUp, installDir, version, ensureDotNetAvailable);
|
||||||
return BuildScript.Bind(installScript, installed =>
|
return BuildScript.Bind(installScript, installed =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
private string FullVersion =>
|
private string FullVersion =>
|
||||||
version.ToString();
|
version.ToString();
|
||||||
|
|
||||||
public string FullPath => Path.Join(dir, FullVersion);
|
public string FullPath => Path.Combine(dir, FullVersion);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The full path to the reference assemblies for this runtime.
|
* The full path to the reference assemblies for this runtime.
|
||||||
@@ -33,7 +33,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
{
|
{
|
||||||
directories[^2] = "packs";
|
directories[^2] = "packs";
|
||||||
directories[^1] = $"{directories[^1]}.Ref";
|
directories[^1] = $"{directories[^1]}.Ref";
|
||||||
return Path.Join(string.Join(Path.DirectorySeparatorChar, directories), FullVersion, "ref");
|
return Path.Combine(string.Join(Path.DirectorySeparatorChar, directories), FullVersion, "ref");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,304 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using Semmle.Util;
|
||||||
|
|
||||||
|
namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Manage the downloading of NuGet packages with nuget.exe.
|
||||||
|
/// Locates packages in a source tree and downloads all of the
|
||||||
|
/// referenced assemblies to a temp folder.
|
||||||
|
/// </summary>
|
||||||
|
internal class NugetExeWrapper : IDisposable
|
||||||
|
{
|
||||||
|
private readonly string? nugetExe;
|
||||||
|
private readonly Semmle.Util.Logging.ILogger logger;
|
||||||
|
|
||||||
|
public int PackageCount => fileProvider.PackagesConfigs.Count;
|
||||||
|
|
||||||
|
private readonly string? backupNugetConfig;
|
||||||
|
private readonly string? nugetConfigPath;
|
||||||
|
private readonly FileProvider fileProvider;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The packages directory.
|
||||||
|
/// This will be in the user-specified or computed Temp location
|
||||||
|
/// so as to not trample the source tree.
|
||||||
|
/// </summary>
|
||||||
|
private readonly DependencyDirectory packageDirectory;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create the package manager for a specified source tree.
|
||||||
|
/// </summary>
|
||||||
|
public NugetExeWrapper(FileProvider fileProvider, DependencyDirectory packageDirectory, Semmle.Util.Logging.ILogger logger, Func<bool> useDefaultFeed)
|
||||||
|
{
|
||||||
|
this.fileProvider = fileProvider;
|
||||||
|
this.packageDirectory = packageDirectory;
|
||||||
|
this.logger = logger;
|
||||||
|
|
||||||
|
if (fileProvider.PackagesConfigs.Count > 0)
|
||||||
|
{
|
||||||
|
logger.LogInfo($"Found packages.config files, trying to use nuget.exe for package restore");
|
||||||
|
nugetExe = ResolveNugetExe();
|
||||||
|
if (HasNoPackageSource() && useDefaultFeed())
|
||||||
|
{
|
||||||
|
// We only modify or add a top level nuget.config file
|
||||||
|
nugetConfigPath = Path.Combine(fileProvider.SourceDir.FullName, "nuget.config");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (File.Exists(nugetConfigPath))
|
||||||
|
{
|
||||||
|
var tempFolderPath = FileUtils.GetTemporaryWorkingDirectory(out _);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
backupNugetConfig = Path.Combine(tempFolderPath, Path.GetRandomFileName());
|
||||||
|
}
|
||||||
|
while (File.Exists(backupNugetConfig));
|
||||||
|
File.Copy(nugetConfigPath, backupNugetConfig, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
File.WriteAllText(nugetConfigPath,
|
||||||
|
"""
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<packageSources>
|
||||||
|
</packageSources>
|
||||||
|
</configuration>
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
AddDefaultPackageSource(nugetConfigPath);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogError($"Failed to add default package source to {nugetConfigPath}: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to find the location of `nuget.exe`. It looks for
|
||||||
|
/// - the environment variable specifying a location,
|
||||||
|
/// - files in the repository,
|
||||||
|
/// - tries to resolve nuget from the PATH, or
|
||||||
|
/// - downloads it if it is not found.
|
||||||
|
/// </summary>
|
||||||
|
private string ResolveNugetExe()
|
||||||
|
{
|
||||||
|
var envVarPath = Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetExePath);
|
||||||
|
if (!string.IsNullOrEmpty(envVarPath))
|
||||||
|
{
|
||||||
|
logger.LogInfo($"Using nuget.exe from environment variable: '{envVarPath}'");
|
||||||
|
return envVarPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return DownloadNugetExe(fileProvider.SourceDir.FullName);
|
||||||
|
}
|
||||||
|
catch (Exception exc)
|
||||||
|
{
|
||||||
|
logger.LogInfo($"Download of nuget.exe failed: {exc.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var nugetExesInRepo = fileProvider.NugetExes;
|
||||||
|
if (nugetExesInRepo.Count > 1)
|
||||||
|
{
|
||||||
|
logger.LogInfo($"Found multiple nuget.exe files in the repository: {string.Join(", ", nugetExesInRepo.OrderBy(s => s))}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nugetExesInRepo.Count > 0)
|
||||||
|
{
|
||||||
|
var path = nugetExesInRepo.First();
|
||||||
|
logger.LogInfo($"Using nuget.exe from path '{path}'");
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
var executableName = Win32.IsWindows() ? "nuget.exe" : "nuget";
|
||||||
|
var nugetPath = FileUtils.FindProgramOnPath(executableName);
|
||||||
|
if (nugetPath is not null)
|
||||||
|
{
|
||||||
|
nugetPath = Path.Combine(nugetPath, executableName);
|
||||||
|
logger.LogInfo($"Using nuget.exe from PATH: {nugetPath}");
|
||||||
|
return nugetPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception("Could not find or download nuget.exe.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private string DownloadNugetExe(string sourceDir)
|
||||||
|
{
|
||||||
|
var directory = Path.Combine(sourceDir, ".nuget");
|
||||||
|
var nuget = Path.Combine(directory, "nuget.exe");
|
||||||
|
|
||||||
|
// Nuget.exe already exists in the .nuget directory.
|
||||||
|
if (File.Exists(nuget))
|
||||||
|
{
|
||||||
|
logger.LogInfo($"Found nuget.exe at {nuget}");
|
||||||
|
return nuget;
|
||||||
|
}
|
||||||
|
|
||||||
|
Directory.CreateDirectory(directory);
|
||||||
|
logger.LogInfo("Attempting to download nuget.exe");
|
||||||
|
FileUtils.DownloadFile(FileUtils.NugetExeUrl, nuget, logger);
|
||||||
|
logger.LogInfo($"Downloaded nuget.exe to {nuget}");
|
||||||
|
return nuget;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool RunWithMono => !Win32.IsWindows() && !string.IsNullOrEmpty(Path.GetExtension(nugetExe));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Restore all packages in the specified packages.config file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="packagesConfig">The packages.config file.</param>
|
||||||
|
private bool TryRestoreNugetPackage(string packagesConfig)
|
||||||
|
{
|
||||||
|
logger.LogInfo($"Restoring file \"{packagesConfig}\"...");
|
||||||
|
|
||||||
|
/* Use nuget.exe to install a package.
|
||||||
|
* Note that there is a clutch of NuGet assemblies which could be used to
|
||||||
|
* invoke this directly, which would arguably be nicer. However they are
|
||||||
|
* really unwieldy and this solution works for now.
|
||||||
|
*/
|
||||||
|
|
||||||
|
string exe, args;
|
||||||
|
if (RunWithMono)
|
||||||
|
{
|
||||||
|
exe = "mono";
|
||||||
|
args = $"\"{nugetExe}\" install -OutputDirectory \"{packageDirectory}\" \"{packagesConfig}\"";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
exe = nugetExe!;
|
||||||
|
args = $"install -OutputDirectory \"{packageDirectory}\" \"{packagesConfig}\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
var pi = new ProcessStartInfo(exe, args)
|
||||||
|
{
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
UseShellExecute = false
|
||||||
|
};
|
||||||
|
|
||||||
|
var threadId = Environment.CurrentManagedThreadId;
|
||||||
|
void onOut(string s) => logger.LogDebug(s, threadId);
|
||||||
|
void onError(string s) => logger.LogError(s, threadId);
|
||||||
|
var exitCode = pi.ReadOutput(out _, onOut, onError);
|
||||||
|
if (exitCode != 0)
|
||||||
|
{
|
||||||
|
logger.LogError($"Command {pi.FileName} {pi.Arguments} failed with exit code {exitCode}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.LogInfo($"Restored file \"{packagesConfig}\"");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Download the packages to the temp folder.
|
||||||
|
/// </summary>
|
||||||
|
public int InstallPackages()
|
||||||
|
{
|
||||||
|
return fileProvider.PackagesConfigs.Count(TryRestoreNugetPackage);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool HasNoPackageSource()
|
||||||
|
{
|
||||||
|
if (Win32.IsWindows())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logger.LogInfo("Checking if default package source is available...");
|
||||||
|
RunMonoNugetCommand("sources list -ForceEnglishOutput", out var stdout);
|
||||||
|
if (stdout.All(line => line != "No sources found."))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogWarning($"Failed to check if default package source is added: {e}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RunMonoNugetCommand(string command, out IList<string> stdout)
|
||||||
|
{
|
||||||
|
string exe, args;
|
||||||
|
if (RunWithMono)
|
||||||
|
{
|
||||||
|
exe = "mono";
|
||||||
|
args = $"\"{nugetExe}\" {command}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
exe = nugetExe!;
|
||||||
|
args = command;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pi = new ProcessStartInfo(exe, args)
|
||||||
|
{
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
UseShellExecute = false
|
||||||
|
};
|
||||||
|
|
||||||
|
var threadId = Environment.CurrentManagedThreadId;
|
||||||
|
void onOut(string s) => logger.LogDebug(s, threadId);
|
||||||
|
void onError(string s) => logger.LogError(s, threadId);
|
||||||
|
pi.ReadOutput(out stdout, onOut, onError);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddDefaultPackageSource(string nugetConfig)
|
||||||
|
{
|
||||||
|
logger.LogInfo("Adding default package source...");
|
||||||
|
RunMonoNugetCommand($"sources add -Name DefaultNugetOrg -Source {NugetPackageRestorer.PublicNugetOrgFeed} -ConfigFile \"{nugetConfig}\"", out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (nugetConfigPath is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (backupNugetConfig is null)
|
||||||
|
{
|
||||||
|
logger.LogInfo("Removing nuget.config file");
|
||||||
|
File.Delete(nugetConfigPath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogInfo("Reverting nuget.config file content");
|
||||||
|
// The content of the original nuget.config file is reverted without changing the file's attributes or casing:
|
||||||
|
using (var backup = File.OpenRead(backupNugetConfig))
|
||||||
|
using (var current = File.OpenWrite(nugetConfigPath))
|
||||||
|
{
|
||||||
|
current.SetLength(0); // Truncate file
|
||||||
|
backup.CopyTo(current); // Restore original content
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogInfo("Deleting backup nuget.config file");
|
||||||
|
File.Delete(backupNugetConfig);
|
||||||
|
}
|
||||||
|
catch (Exception exc)
|
||||||
|
{
|
||||||
|
logger.LogError($"Failed to restore original nuget.config file: {exc}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -161,13 +161,13 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
reachableFeeds.UnionWith(reachableInheritedFeeds);
|
reachableFeeds.UnionWith(reachableInheritedFeeds);
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var packagesConfigRestore = PackagesConfigRestoreFactory.Create(fileProvider, legacyPackageDirectory, logger, IsDefaultFeedReachable))
|
using (var nuget = new NugetExeWrapper(fileProvider, legacyPackageDirectory, logger, IsDefaultFeedReachable))
|
||||||
{
|
{
|
||||||
var count = packagesConfigRestore.InstallPackages();
|
var count = nuget.InstallPackages();
|
||||||
|
|
||||||
if (packagesConfigRestore.PackageCount > 0)
|
if (nuget.PackageCount > 0)
|
||||||
{
|
{
|
||||||
compilationInfoContainer.CompilationInfos.Add(("packages.config files", packagesConfigRestore.PackageCount.ToString()));
|
compilationInfoContainer.CompilationInfos.Add(("packages.config files", nuget.PackageCount.ToString()));
|
||||||
compilationInfoContainer.CompilationInfos.Add(("Successfully restored packages.config files", count.ToString()));
|
compilationInfoContainer.CompilationInfos.Add(("Successfully restored packages.config files", count.ToString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -209,7 +209,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
|
|
||||||
var paths = dependencies
|
var paths = dependencies
|
||||||
.Paths
|
.Paths
|
||||||
.Select(d => Path.Join(PackageDirectory.DirInfo.FullName, d))
|
.Select(d => Path.Combine(PackageDirectory.DirInfo.FullName, d))
|
||||||
.ToList();
|
.ToList();
|
||||||
assemblyLookupLocations.UnionWith(paths.Select(p => new AssemblyLookupLocation(p)));
|
assemblyLookupLocations.UnionWith(paths.Select(p => new AssemblyLookupLocation(p)));
|
||||||
|
|
||||||
@@ -527,7 +527,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
fallbackNugetFeeds.ForEach((feed, index) => sb.AppendLine($"<add key=\"feed{index}\" value=\"{feed}\" />"));
|
fallbackNugetFeeds.ForEach((feed, index) => sb.AppendLine($"<add key=\"feed{index}\" value=\"{feed}\" />"));
|
||||||
|
|
||||||
var nugetConfigPath = Path.Join(folderPath, "nuget.config");
|
var nugetConfigPath = Path.Combine(folderPath, "nuget.config");
|
||||||
logger.LogInfo($"Creating fallback nuget.config file {nugetConfigPath}.");
|
logger.LogInfo($"Creating fallback nuget.config file {nugetConfigPath}.");
|
||||||
File.WriteAllText(nugetConfigPath,
|
File.WriteAllText(nugetConfigPath,
|
||||||
$"""
|
$"""
|
||||||
@@ -1052,7 +1052,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private static string ComputeTempDirectoryPath(string subfolderName)
|
private static string ComputeTempDirectoryPath(string subfolderName)
|
||||||
{
|
{
|
||||||
return Path.Join(FileUtils.GetTemporaryWorkingDirectory(out _), subfolderName);
|
return Path.Combine(FileUtils.GetTemporaryWorkingDirectory(out _), subfolderName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1060,7 +1060,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private static string ComputeTempDirectoryPath(string srcDir, string subfolderName)
|
private static string ComputeTempDirectoryPath(string srcDir, string subfolderName)
|
||||||
{
|
{
|
||||||
return Path.Join(FileUtils.GetTemporaryWorkingDirectory(out _), FileUtils.ComputeHash(srcDir), subfolderName);
|
return Path.Combine(FileUtils.GetTemporaryWorkingDirectory(out _), FileUtils.ComputeHash(srcDir), subfolderName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,368 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using Semmle.Util;
|
|
||||||
|
|
||||||
namespace Semmle.Extraction.CSharp.DependencyFetching
|
|
||||||
{
|
|
||||||
internal interface IPackagesConfigRestore : IDisposable
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The number of packages.config files found in the source tree.
|
|
||||||
/// </summary>
|
|
||||||
int PackageCount { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Download the packages to the temp folder.
|
|
||||||
/// </summary>
|
|
||||||
int InstallPackages();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Factory for creating a package manager to restore NuGet packages referenced in packages.config files.
|
|
||||||
/// If the environment doesn't support using nuget.exe to restore packages from packages.config files, a no-op implementation is returned.
|
|
||||||
/// It is worth noting that for macOS and Linux, nuget.exe is used with mono. However, mono is being deprecated and the last GitHub images
|
|
||||||
/// to contain mono are:
|
|
||||||
/// - Ubuntu 22.04
|
|
||||||
/// - macOS 14
|
|
||||||
///
|
|
||||||
/// If the packages from the packages.config files are not restored with the packages.config restore functionality below, there is a subsequent
|
|
||||||
/// step that still may succeed in restoring the packages without the help of nuget.exe (by attempting to restore using dotnet).
|
|
||||||
/// </summary>
|
|
||||||
internal class PackagesConfigRestoreFactory
|
|
||||||
{
|
|
||||||
public static IPackagesConfigRestore Create(FileProvider fileProvider, DependencyDirectory packageDirectory, Semmle.Util.Logging.ILogger logger, Func<bool> useDefaultFeed)
|
|
||||||
{
|
|
||||||
if (SystemBuildActions.Instance.IsWindows() || SystemBuildActions.Instance.IsMonoInstalled())
|
|
||||||
{
|
|
||||||
return new NugetExeWrapper(fileProvider, packageDirectory, logger, useDefaultFeed);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new NoOpPackagesConfig(fileProvider, logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Manage the downloading of NuGet packages with nuget.exe.
|
|
||||||
/// Locates packages in a source tree and downloads all of the
|
|
||||||
/// referenced assemblies to a temp folder.
|
|
||||||
/// </summary>
|
|
||||||
private class NugetExeWrapper : IPackagesConfigRestore
|
|
||||||
{
|
|
||||||
private readonly string? nugetExe;
|
|
||||||
private readonly Semmle.Util.Logging.ILogger logger;
|
|
||||||
|
|
||||||
public int PackageCount => fileProvider.PackagesConfigs.Count;
|
|
||||||
|
|
||||||
private readonly string? backupNugetConfig;
|
|
||||||
private readonly string? nugetConfigPath;
|
|
||||||
private readonly FileProvider fileProvider;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The packages directory.
|
|
||||||
/// This will be in the user-specified or computed Temp location
|
|
||||||
/// so as to not trample the source tree.
|
|
||||||
/// </summary>
|
|
||||||
private readonly DependencyDirectory packageDirectory;
|
|
||||||
|
|
||||||
private bool IsWindows => SystemBuildActions.Instance.IsWindows();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create the package manager for a specified source tree.
|
|
||||||
/// </summary>
|
|
||||||
public NugetExeWrapper(FileProvider fileProvider, DependencyDirectory packageDirectory, Semmle.Util.Logging.ILogger logger, Func<bool> useDefaultFeed)
|
|
||||||
{
|
|
||||||
this.fileProvider = fileProvider;
|
|
||||||
this.packageDirectory = packageDirectory;
|
|
||||||
this.logger = logger;
|
|
||||||
|
|
||||||
if (fileProvider.PackagesConfigs.Count > 0)
|
|
||||||
{
|
|
||||||
logger.LogInfo($"Found packages.config files, trying to use nuget.exe for package restore");
|
|
||||||
nugetExe = ResolveNugetExe();
|
|
||||||
if (!HasPackageSource() && useDefaultFeed())
|
|
||||||
{
|
|
||||||
// We only modify or add a top level nuget.config file
|
|
||||||
nugetConfigPath = Path.Join(fileProvider.SourceDir.FullName, "nuget.config");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (File.Exists(nugetConfigPath))
|
|
||||||
{
|
|
||||||
var tempFolderPath = FileUtils.GetTemporaryWorkingDirectory(out _);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
backupNugetConfig = Path.Join(tempFolderPath, Path.GetRandomFileName());
|
|
||||||
}
|
|
||||||
while (File.Exists(backupNugetConfig));
|
|
||||||
File.Copy(nugetConfigPath, backupNugetConfig, true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
File.WriteAllText(nugetConfigPath,
|
|
||||||
"""
|
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<configuration>
|
|
||||||
<packageSources>
|
|
||||||
</packageSources>
|
|
||||||
</configuration>
|
|
||||||
""");
|
|
||||||
}
|
|
||||||
AddDefaultPackageSource(nugetConfigPath);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
logger.LogError($"Failed to add default package source to {nugetConfigPath}: {e}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to find the location of `nuget.exe`. It looks for
|
|
||||||
/// - the environment variable specifying a location,
|
|
||||||
/// - files in the repository,
|
|
||||||
/// - tries to resolve nuget from the PATH, or
|
|
||||||
/// - downloads it if it is not found.
|
|
||||||
/// </summary>
|
|
||||||
private string ResolveNugetExe()
|
|
||||||
{
|
|
||||||
var envVarPath = Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetExePath);
|
|
||||||
if (!string.IsNullOrEmpty(envVarPath))
|
|
||||||
{
|
|
||||||
logger.LogInfo($"Using nuget.exe from environment variable: '{envVarPath}'");
|
|
||||||
return envVarPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return DownloadNugetExe(fileProvider.SourceDir.FullName);
|
|
||||||
}
|
|
||||||
catch (Exception exc)
|
|
||||||
{
|
|
||||||
logger.LogInfo($"Download of nuget.exe failed: {exc.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
var nugetExesInRepo = fileProvider.NugetExes;
|
|
||||||
if (nugetExesInRepo.Count > 1)
|
|
||||||
{
|
|
||||||
logger.LogInfo($"Found multiple nuget.exe files in the repository: {string.Join(", ", nugetExesInRepo.OrderBy(s => s))}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nugetExesInRepo.Count > 0)
|
|
||||||
{
|
|
||||||
var path = nugetExesInRepo.First();
|
|
||||||
logger.LogInfo($"Using nuget.exe from path '{path}'");
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
var executableName = IsWindows ? "nuget.exe" : "nuget";
|
|
||||||
var nugetPath = FileUtils.FindProgramOnPath(executableName);
|
|
||||||
if (nugetPath is not null)
|
|
||||||
{
|
|
||||||
nugetPath = Path.Join(nugetPath, executableName);
|
|
||||||
logger.LogInfo($"Using nuget.exe from PATH: {nugetPath}");
|
|
||||||
return nugetPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Exception("Could not find or download nuget.exe.");
|
|
||||||
}
|
|
||||||
|
|
||||||
private string DownloadNugetExe(string sourceDir)
|
|
||||||
{
|
|
||||||
var directory = Path.Join(sourceDir, ".nuget");
|
|
||||||
var nuget = Path.Join(directory, "nuget.exe");
|
|
||||||
|
|
||||||
// Nuget.exe already exists in the .nuget directory.
|
|
||||||
if (File.Exists(nuget))
|
|
||||||
{
|
|
||||||
logger.LogInfo($"Found nuget.exe at {nuget}");
|
|
||||||
return nuget;
|
|
||||||
}
|
|
||||||
|
|
||||||
Directory.CreateDirectory(directory);
|
|
||||||
logger.LogInfo("Attempting to download nuget.exe");
|
|
||||||
FileUtils.DownloadFile(FileUtils.NugetExeUrl, nuget, logger);
|
|
||||||
logger.LogInfo($"Downloaded nuget.exe to {nuget}");
|
|
||||||
return nuget;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool RunWithMono => !IsWindows && !string.IsNullOrEmpty(Path.GetExtension(nugetExe));
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Restore all packages in the specified packages.config file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="packagesConfig">The packages.config file.</param>
|
|
||||||
private bool TryRestoreNugetPackage(string packagesConfig)
|
|
||||||
{
|
|
||||||
logger.LogInfo($"Restoring file \"{packagesConfig}\"...");
|
|
||||||
|
|
||||||
/* Use nuget.exe to install a package.
|
|
||||||
* Note that there is a clutch of NuGet assemblies which could be used to
|
|
||||||
* invoke this directly, which would arguably be nicer. However they are
|
|
||||||
* really unwieldy and this solution works for now.
|
|
||||||
*/
|
|
||||||
|
|
||||||
string exe, args;
|
|
||||||
if (RunWithMono)
|
|
||||||
{
|
|
||||||
exe = "mono";
|
|
||||||
args = $"\"{nugetExe}\" install -OutputDirectory \"{packageDirectory}\" \"{packagesConfig}\"";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
exe = nugetExe!;
|
|
||||||
args = $"install -OutputDirectory \"{packageDirectory}\" \"{packagesConfig}\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
var pi = new ProcessStartInfo(exe, args)
|
|
||||||
{
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
RedirectStandardError = true,
|
|
||||||
UseShellExecute = false
|
|
||||||
};
|
|
||||||
|
|
||||||
var threadId = Environment.CurrentManagedThreadId;
|
|
||||||
void onOut(string s) => logger.LogDebug(s, threadId);
|
|
||||||
void onError(string s) => logger.LogError(s, threadId);
|
|
||||||
var exitCode = pi.ReadOutput(out _, onOut, onError);
|
|
||||||
if (exitCode != 0)
|
|
||||||
{
|
|
||||||
logger.LogError($"Command {pi.FileName} {pi.Arguments} failed with exit code {exitCode}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.LogInfo($"Restored file \"{packagesConfig}\"");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Download the packages to the temp folder.
|
|
||||||
/// </summary>
|
|
||||||
public int InstallPackages()
|
|
||||||
{
|
|
||||||
return fileProvider.PackagesConfigs.Count(TryRestoreNugetPackage);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool HasPackageSource()
|
|
||||||
{
|
|
||||||
if (IsWindows)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
logger.LogInfo("Checking if default package source is available...");
|
|
||||||
RunMonoNugetCommand("sources list -ForceEnglishOutput", out var stdout);
|
|
||||||
if (stdout.All(line => line != "No sources found."))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
logger.LogWarning($"Failed to check if default package source is added: {e}");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RunMonoNugetCommand(string command, out IList<string> stdout)
|
|
||||||
{
|
|
||||||
string exe, args;
|
|
||||||
if (RunWithMono)
|
|
||||||
{
|
|
||||||
exe = "mono";
|
|
||||||
args = $"\"{nugetExe}\" {command}";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
exe = nugetExe!;
|
|
||||||
args = command;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pi = new ProcessStartInfo(exe, args)
|
|
||||||
{
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
RedirectStandardError = true,
|
|
||||||
UseShellExecute = false
|
|
||||||
};
|
|
||||||
|
|
||||||
var threadId = Environment.CurrentManagedThreadId;
|
|
||||||
void onOut(string s) => logger.LogDebug(s, threadId);
|
|
||||||
void onError(string s) => logger.LogError(s, threadId);
|
|
||||||
pi.ReadOutput(out stdout, onOut, onError);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddDefaultPackageSource(string nugetConfig)
|
|
||||||
{
|
|
||||||
logger.LogInfo("Adding default package source...");
|
|
||||||
RunMonoNugetCommand($"sources add -Name DefaultNugetOrg -Source {NugetPackageRestorer.PublicNugetOrgFeed} -ConfigFile \"{nugetConfig}\"", out _);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (nugetConfigPath is null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (backupNugetConfig is null)
|
|
||||||
{
|
|
||||||
logger.LogInfo("Removing nuget.config file");
|
|
||||||
File.Delete(nugetConfigPath);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.LogInfo("Reverting nuget.config file content");
|
|
||||||
// The content of the original nuget.config file is reverted without changing the file's attributes or casing:
|
|
||||||
using (var backup = File.OpenRead(backupNugetConfig))
|
|
||||||
using (var current = File.OpenWrite(nugetConfigPath))
|
|
||||||
{
|
|
||||||
current.SetLength(0); // Truncate file
|
|
||||||
backup.CopyTo(current); // Restore original content
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.LogInfo("Deleting backup nuget.config file");
|
|
||||||
File.Delete(backupNugetConfig);
|
|
||||||
}
|
|
||||||
catch (Exception exc)
|
|
||||||
{
|
|
||||||
logger.LogError($"Failed to restore original nuget.config file: {exc}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class NoOpPackagesConfig : IPackagesConfigRestore
|
|
||||||
{
|
|
||||||
private readonly Semmle.Util.Logging.ILogger logger;
|
|
||||||
private readonly FileProvider fileProvider;
|
|
||||||
|
|
||||||
public NoOpPackagesConfig(FileProvider fileProvider, Semmle.Util.Logging.ILogger logger)
|
|
||||||
{
|
|
||||||
this.fileProvider = fileProvider;
|
|
||||||
this.logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int PackageCount => fileProvider.PackagesConfigs.Count;
|
|
||||||
|
|
||||||
public int InstallPackages()
|
|
||||||
{
|
|
||||||
if (PackageCount > 0)
|
|
||||||
{
|
|
||||||
logger.LogInfo("Found packages.config files, but nuget.exe cannot be used to restore packages on this platform. Skipping restore of packages.config files.");
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -79,7 +79,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
|
|
||||||
var monoPath = FileUtils.FindProgramOnPath(Win32.IsWindows() ? "mono.exe" : "mono");
|
var monoPath = FileUtils.FindProgramOnPath(Win32.IsWindows() ? "mono.exe" : "mono");
|
||||||
string[] monoDirs = monoPath is not null
|
string[] monoDirs = monoPath is not null
|
||||||
? [Path.GetFullPath(Path.Join(monoPath, "..", "lib", "mono")), monoPath]
|
? [Path.GetFullPath(Path.Combine(monoPath, "..", "lib", "mono")), monoPath]
|
||||||
: ["/usr/lib/mono", "/usr/local/mono", "/usr/local/bin/mono", @"C:\Program Files\Mono\lib\mono"];
|
: ["/usr/lib/mono", "/usr/local/mono", "/usr/local/bin/mono", @"C:\Program Files\Mono\lib\mono"];
|
||||||
|
|
||||||
var monoDir = monoDirs.FirstOrDefault(Directory.Exists);
|
var monoDir = monoDirs.FirstOrDefault(Directory.Exists);
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var path = Path.Join(version.FullPath, "Roslyn", "bincore", "csc.dll");
|
var path = Path.Combine(version.FullPath, "Roslyn", "bincore", "csc.dll");
|
||||||
logger.LogDebug($"Source generator CSC: '{path}'");
|
logger.LogDebug($"Source generator CSC: '{path}'");
|
||||||
if (!File.Exists(path))
|
if (!File.Exists(path))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,10 +41,10 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
.Replace('\\', '/'); // Ensure we're generating the same hash regardless of the OS
|
.Replace('\\', '/'); // Ensure we're generating the same hash regardless of the OS
|
||||||
var name = FileUtils.ComputeHash($"{relativePathToCsProj}\n{this.GetType().Name}");
|
var name = FileUtils.ComputeHash($"{relativePathToCsProj}\n{this.GetType().Name}");
|
||||||
using var tempDir = new TemporaryDirectory(Path.Join(FileUtils.GetTemporaryWorkingDirectory(out _), "source-generator"), "source generator temporary", logger);
|
using var tempDir = new TemporaryDirectory(Path.Join(FileUtils.GetTemporaryWorkingDirectory(out _), "source-generator"), "source generator temporary", logger);
|
||||||
var analyzerConfigPath = Path.Join(tempDir.DirInfo.FullName, $"{name}.txt");
|
var analyzerConfigPath = Path.Combine(tempDir.DirInfo.FullName, $"{name}.txt");
|
||||||
var dllPath = Path.Join(tempDir.DirInfo.FullName, $"{name}.dll");
|
var dllPath = Path.Combine(tempDir.DirInfo.FullName, $"{name}.dll");
|
||||||
var cscArgsPath = Path.Join(tempDir.DirInfo.FullName, $"{name}.rsp");
|
var cscArgsPath = Path.Combine(tempDir.DirInfo.FullName, $"{name}.rsp");
|
||||||
var outputFolder = Path.Join(targetDir, name);
|
var outputFolder = Path.Combine(targetDir, name);
|
||||||
Directory.CreateDirectory(outputFolder);
|
Directory.CreateDirectory(outputFolder);
|
||||||
logger.LogInfo("Producing analyzer config content.");
|
logger.LogInfo("Producing analyzer config content.");
|
||||||
GenerateAnalyzerConfig(additionalFiles, csprojFile, analyzerConfigPath);
|
GenerateAnalyzerConfig(additionalFiles, csprojFile, analyzerConfigPath);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
throw new Exception("No SDK path available.");
|
throw new Exception("No SDK path available.");
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceGeneratorFolder = Path.Join(sdkPath, "Sdks", "Microsoft.NET.Sdk.Razor", "source-generators");
|
SourceGeneratorFolder = Path.Combine(sdkPath, "Sdks", "Microsoft.NET.Sdk.Razor", "source-generators");
|
||||||
this.logger.LogInfo($"Razor source generator folder: {SourceGeneratorFolder}");
|
this.logger.LogInfo($"Razor source generator folder: {SourceGeneratorFolder}");
|
||||||
if (!Directory.Exists(SourceGeneratorFolder))
|
if (!Directory.Exists(SourceGeneratorFolder))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
if (usings.Count > 0)
|
if (usings.Count > 0)
|
||||||
{
|
{
|
||||||
var tempDir = GetTemporaryWorkingDirectory("implicitUsings");
|
var tempDir = GetTemporaryWorkingDirectory("implicitUsings");
|
||||||
var path = Path.Join(tempDir, "GlobalUsings.g.cs");
|
var path = Path.Combine(tempDir, "GlobalUsings.g.cs");
|
||||||
using (var writer = new StreamWriter(path))
|
using (var writer = new StreamWriter(path))
|
||||||
{
|
{
|
||||||
writer.WriteLine("// <auto-generated/>");
|
writer.WriteLine("// <auto-generated/>");
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
var nugetFolder = nugetPackageRestorer.TryRestore("Microsoft.CodeAnalysis.ResxSourceGenerator");
|
var nugetFolder = nugetPackageRestorer.TryRestore("Microsoft.CodeAnalysis.ResxSourceGenerator");
|
||||||
if (nugetFolder is not null)
|
if (nugetFolder is not null)
|
||||||
{
|
{
|
||||||
sourceGeneratorFolder = System.IO.Path.Join(nugetFolder, "analyzers", "dotnet", "cs");
|
sourceGeneratorFolder = System.IO.Path.Combine(nugetFolder, "analyzers", "dotnet", "cs");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected string GetTemporaryWorkingDirectory(string subfolder)
|
protected string GetTemporaryWorkingDirectory(string subfolder)
|
||||||
{
|
{
|
||||||
var temp = Path.Join(tempWorkingDirectory.ToString(), subfolder);
|
var temp = Path.Combine(tempWorkingDirectory.ToString(), subfolder);
|
||||||
Directory.CreateDirectory(temp);
|
Directory.CreateDirectory(temp);
|
||||||
|
|
||||||
return temp;
|
return temp;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.CodeAnalysis.CSharp;
|
|
||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
using Semmle.Extraction.Kinds;
|
using Semmle.Extraction.Kinds;
|
||||||
|
|
||||||
@@ -9,7 +8,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
|||||||
internal abstract class ElementAccess : Expression<ExpressionSyntax>
|
internal abstract class ElementAccess : Expression<ExpressionSyntax>
|
||||||
{
|
{
|
||||||
protected ElementAccess(ExpressionNodeInfo info, ExpressionSyntax qualifier, BracketedArgumentListSyntax argumentList)
|
protected ElementAccess(ExpressionNodeInfo info, ExpressionSyntax qualifier, BracketedArgumentListSyntax argumentList)
|
||||||
: base(info.SetKind(GetKind(info.Context, info.Node, qualifier)))
|
: base(info.SetKind(GetKind(info.Context, qualifier)))
|
||||||
{
|
{
|
||||||
this.qualifier = qualifier;
|
this.qualifier = qualifier;
|
||||||
this.argumentList = argumentList;
|
this.argumentList = argumentList;
|
||||||
@@ -18,125 +17,6 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
|||||||
private readonly ExpressionSyntax qualifier;
|
private readonly ExpressionSyntax qualifier;
|
||||||
private readonly BracketedArgumentListSyntax argumentList;
|
private readonly BracketedArgumentListSyntax argumentList;
|
||||||
|
|
||||||
|
|
||||||
private ISymbol? GetTargetSymbol()
|
|
||||||
{
|
|
||||||
return Context.GetSymbolInfo(base.Syntax).Symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void SetExprArgument(TextWriter trapFile, Expression left, Expression right)
|
|
||||||
{
|
|
||||||
trapFile.expr_argument(left, 0);
|
|
||||||
trapFile.expr_argument(right, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Expression MakeZeroFromEndExpression(IExpressionParentEntity parent, int child)
|
|
||||||
{
|
|
||||||
var info = new ExpressionInfo(
|
|
||||||
Context,
|
|
||||||
AnnotatedTypeSymbol.CreateNotAnnotated(Context.Compilation.GetSpecialType(SpecialType.System_Int32)),
|
|
||||||
Location,
|
|
||||||
ExprKind.INDEX,
|
|
||||||
parent,
|
|
||||||
child,
|
|
||||||
isCompilerGenerated: true,
|
|
||||||
null);
|
|
||||||
|
|
||||||
var index = new Expression(info);
|
|
||||||
|
|
||||||
MakeZeroLiteral(index, 0);
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Expression MakeZeroLiteral(IExpressionParentEntity parent, int child)
|
|
||||||
{
|
|
||||||
return Literal.CreateGenerated(Context, parent, child, Context.Compilation.GetSpecialType(SpecialType.System_Int32), 0, Location);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// It is assumed that either the input is
|
|
||||||
/// 1. A normal expression that can be used as endpoint (e.g a constant like "3").
|
|
||||||
/// 2. An index expression indicating that we should read from the end (e.g "^1").
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="syntax">The syntax node representing the range endpoint.</param>
|
|
||||||
/// <param name="parent">The parent expression entity.</param>
|
|
||||||
/// <param name="child">The child index within the parent.</param>
|
|
||||||
/// <returns>An expression representing the endpoint of a range to be used in conjunction with a slice operation.</returns>
|
|
||||||
private Expression MakeFromRangeEndpoint(ExpressionSyntax syntax, IExpressionParentEntity parent, int child)
|
|
||||||
{
|
|
||||||
var info = new ExpressionNodeInfo(Context, syntax, parent, child);
|
|
||||||
|
|
||||||
return syntax.Kind() == SyntaxKind.IndexExpression
|
|
||||||
? PrefixUnary.Create(info.SetKind(ExprKind.INDEX))
|
|
||||||
: Factory.Create(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines whether the given method is a slice method, which is defined as a method with
|
|
||||||
/// the name "Slice" or "Substring" and two parameters.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="method">The method symbol to check.</param>
|
|
||||||
/// <returns>True if the method is a slice method; false otherwise.</returns>
|
|
||||||
private bool IsSlice(IMethodSymbol method, out RangeExpressionSyntax? range)
|
|
||||||
{
|
|
||||||
range = null;
|
|
||||||
|
|
||||||
if (argumentList.Arguments.Count == 1)
|
|
||||||
{
|
|
||||||
range = argumentList.Arguments[0].Expression as RangeExpressionSyntax;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (method.Name == "Slice" || method.Name == "Substring")
|
|
||||||
&& method.Parameters.Length == 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Populates a slice method call based on the given range.
|
|
||||||
/// Roslyn translates indexer accesses with range expressions in the following way.
|
|
||||||
/// 1. s[a..b] -> s.Slice(a, b - a)
|
|
||||||
/// 2. s[..b] -> s.Slice(0, b)
|
|
||||||
/// 3. s[a..] -> s.Slice(a, s.Length - a)
|
|
||||||
/// 4. s[..] -> s.Slice(0, s.Length)
|
|
||||||
/// However, it is possible that both the qualifier or the index endpoints may contain method calls.
|
|
||||||
/// If we want to translate this accurately, we would need to introduce synthetic statements for qualifier and
|
|
||||||
/// the endpoints, which should then be used in the slice method call.
|
|
||||||
/// To avoid this, we translate as follows.
|
|
||||||
/// 1. s[a..b] -> s.Slice(a, b)
|
|
||||||
/// 2. s[..b] -> s.Slice(0, b)
|
|
||||||
/// 3. s[a..] -> s.Slice(a, ^0)
|
|
||||||
/// 4. s[..] -> s.Slice(0, ^0)
|
|
||||||
///
|
|
||||||
/// Even though index expressions can't technically be used in this way, they signal that we
|
|
||||||
/// could perceive ^b as "length - b".
|
|
||||||
///
|
|
||||||
/// Call arguments are only populated when a range expression is directly available in
|
|
||||||
/// the list of arguments.
|
|
||||||
/// This means that cases like below are not handled.
|
|
||||||
/// System.Range x = 1..3;
|
|
||||||
/// s[x]
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="trapFile">The trap file to write to.</param>
|
|
||||||
/// <param name="slice">The slice method symbol.</param>
|
|
||||||
/// <param name="range">The range expression syntax.</param>
|
|
||||||
private void PopulateSlice(TextWriter trapFile, IMethodSymbol slice, RangeExpressionSyntax? range)
|
|
||||||
{
|
|
||||||
if (range is not null)
|
|
||||||
{
|
|
||||||
// Populate the call arguments
|
|
||||||
var left = range.LeftOperand is ExpressionSyntax lsyntax
|
|
||||||
? MakeFromRangeEndpoint(lsyntax, this, 0)
|
|
||||||
: MakeZeroLiteral(this, 0);
|
|
||||||
|
|
||||||
var right = range.RightOperand is ExpressionSyntax rsyntax
|
|
||||||
? MakeFromRangeEndpoint(rsyntax, this, 1)
|
|
||||||
: MakeZeroFromEndExpression(this, 1);
|
|
||||||
|
|
||||||
SetExprArgument(trapFile, left, right);
|
|
||||||
}
|
|
||||||
trapFile.expr_call(this, Method.Create(Context, slice));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void PopulateExpression(TextWriter trapFile)
|
protected override void PopulateExpression(TextWriter trapFile)
|
||||||
{
|
{
|
||||||
if (Kind == ExprKind.POINTER_INDIRECTION)
|
if (Kind == ExprKind.POINTER_INDIRECTION)
|
||||||
@@ -150,19 +30,11 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Create(Context, qualifier, this, -1);
|
Create(Context, qualifier, this, -1);
|
||||||
|
|
||||||
var target = GetTargetSymbol();
|
|
||||||
if (target is IMethodSymbol method && IsSlice(method, out var range))
|
|
||||||
{
|
|
||||||
// When an indexer on a span or string is used in conjunction with a range expression, the compiler translates
|
|
||||||
// this into a call to the "Slice" or "Substring" method.
|
|
||||||
// In this case, we want to populate a slice/substring method call instead of an indexer access.
|
|
||||||
PopulateSlice(trapFile, method, range);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PopulateArguments(trapFile, argumentList, 0);
|
PopulateArguments(trapFile, argumentList, 0);
|
||||||
if (target is IPropertySymbol { IsIndexer: true } indexer)
|
|
||||||
|
var symbolInfo = Context.GetSymbolInfo(base.Syntax);
|
||||||
|
|
||||||
|
if (symbolInfo.Symbol is IPropertySymbol indexer)
|
||||||
{
|
{
|
||||||
trapFile.expr_access(this, Indexer.Create(Context, indexer));
|
trapFile.expr_access(this, Indexer.Create(Context, indexer));
|
||||||
}
|
}
|
||||||
@@ -174,11 +46,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
|||||||
private static bool IsArray(ITypeSymbol symbol) =>
|
private static bool IsArray(ITypeSymbol symbol) =>
|
||||||
symbol.TypeKind == Microsoft.CodeAnalysis.TypeKind.Array || symbol.IsInlineArray();
|
symbol.TypeKind == Microsoft.CodeAnalysis.TypeKind.Array || symbol.IsInlineArray();
|
||||||
|
|
||||||
private static ExprKind GetKind(Context cx, ExpressionSyntax syntax, ExpressionSyntax qualifier)
|
private static ExprKind GetKind(Context cx, ExpressionSyntax qualifier)
|
||||||
{
|
{
|
||||||
if (cx.GetSymbolInfo(syntax).Symbol is IMethodSymbol)
|
|
||||||
return ExprKind.METHOD_INVOCATION;
|
|
||||||
|
|
||||||
var qualifierType = cx.GetType(qualifier);
|
var qualifierType = cx.GetType(qualifier);
|
||||||
|
|
||||||
// This is a compilation error, so make a guess and continue.
|
// This is a compilation error, so make a guess and continue.
|
||||||
|
|||||||
@@ -23,9 +23,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
|
|||||||
}
|
}
|
||||||
else if (isSpecificCatchClause) // A catch clause of the form 'catch(Ex) { ... }'
|
else if (isSpecificCatchClause) // A catch clause of the form 'catch(Ex) { ... }'
|
||||||
{
|
{
|
||||||
var type = Type.Create(Context, Context.GetType(Stmt.Declaration!.Type));
|
trapFile.catch_type(this, Type.Create(Context, Context.GetType(Stmt.Declaration!.Type)).TypeRef, true);
|
||||||
trapFile.catch_type(this, type.TypeRef, true);
|
|
||||||
TypeMention.Create(Context, Stmt.Declaration!.Type, this, type);
|
|
||||||
}
|
}
|
||||||
else // A catch clause of the form 'catch { ... }'
|
else // A catch clause of the form 'catch { ... }'
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ namespace Semmle.Extraction.CSharp
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mscorlibExists = File.Exists(Path.Join(compilerDir, "mscorlib.dll"));
|
var mscorlibExists = File.Exists(Path.Combine(compilerDir, "mscorlib.dll"));
|
||||||
|
|
||||||
if (specifiedFramework is null && mscorlibExists)
|
if (specifiedFramework is null && mscorlibExists)
|
||||||
{
|
{
|
||||||
@@ -107,7 +107,7 @@ namespace Semmle.Extraction.CSharp
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The file csc.rsp.
|
/// The file csc.rsp.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private string CscRsp => Path.Join(FrameworkPath, csc_rsp);
|
private string CscRsp => Path.Combine(FrameworkPath, csc_rsp);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Should we skip extraction?
|
/// Should we skip extraction?
|
||||||
|
|||||||
@@ -680,7 +680,7 @@ namespace Semmle.Extraction.CSharp
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var fullPath = Path.GetFullPath(Path.Join(Path.GetDirectoryName(mappedFromPath)!, mappedToPath));
|
var fullPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(mappedFromPath)!, mappedToPath));
|
||||||
ExtractionContext.Logger.LogDebug($"Found relative path in line mapping: '{mappedToPath}', interpreting it as '{fullPath}'");
|
ExtractionContext.Logger.LogDebug($"Found relative path in line mapping: '{mappedToPath}', interpreting it as '{fullPath}'");
|
||||||
|
|
||||||
mappedToPath = fullPath;
|
mappedToPath = fullPath;
|
||||||
|
|||||||
@@ -159,11 +159,7 @@ namespace Semmle.Extraction.CSharp
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var normalized = Path.DirectorySeparatorChar == '/' ? file.Replace("\\", "/") : file;
|
return Path.GetFullPath(Path.Combine(projDir?.FullName ?? string.Empty, Path.DirectorySeparatorChar == '/' ? file.Replace("\\", "/") : file));
|
||||||
var path = projDir is not null && !Path.IsPathRooted(normalized)
|
|
||||||
? Path.Join(projDir.FullName, normalized)
|
|
||||||
: normalized;
|
|
||||||
return Path.GetFullPath(path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly string[] references;
|
private readonly string[] references;
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ namespace Semmle.Extraction.CSharp
|
|||||||
TracingAnalyser.GetOutputName(compilation, args),
|
TracingAnalyser.GetOutputName(compilation, args),
|
||||||
compilation,
|
compilation,
|
||||||
generatedSyntaxTrees,
|
generatedSyntaxTrees,
|
||||||
Path.Join(compilationIdentifierPath, diagnosticName),
|
Path.Combine(compilationIdentifierPath, diagnosticName),
|
||||||
options),
|
options),
|
||||||
() => { });
|
() => { });
|
||||||
|
|
||||||
@@ -377,7 +377,7 @@ namespace Semmle.Extraction.CSharp
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var composed = referencePaths.Value
|
var composed = referencePaths.Value
|
||||||
.Select(path => Path.Join(path, clref.Reference))
|
.Select(path => Path.Combine(path, clref.Reference))
|
||||||
.Where(path => File.Exists(path))
|
.Where(path => File.Exists(path))
|
||||||
.Select(path => analyser.PathCache.GetCanonicalPath(path))
|
.Select(path => analyser.PathCache.GetCanonicalPath(path))
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
@@ -559,13 +559,13 @@ namespace Semmle.Extraction.CSharp
|
|||||||
/// Gets the path to the `csharp.log` file written to by the C# extractor.
|
/// Gets the path to the `csharp.log` file written to by the C# extractor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string GetCSharpLogPath() =>
|
public static string GetCSharpLogPath() =>
|
||||||
Path.Join(GetCSharpLogDirectory(), "csharp.log");
|
Path.Combine(GetCSharpLogDirectory(), "csharp.log");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the path to a `csharp.{hash}.txt` file written to by the C# extractor.
|
/// Gets the path to a `csharp.{hash}.txt` file written to by the C# extractor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string GetCSharpArgsLogPath(string hash) =>
|
public static string GetCSharpArgsLogPath(string hash) =>
|
||||||
Path.Join(GetCSharpLogDirectory(), $"csharp.{hash}.txt");
|
Path.Combine(GetCSharpLogDirectory(), $"csharp.{hash}.txt");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a list of all `csharp.{hash}.txt` files currently written to the log directory.
|
/// Gets a list of all `csharp.{hash}.txt` files currently written to the log directory.
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ namespace Semmle.Extraction.CSharp
|
|||||||
return Path.ChangeExtension(entryPointFilename, ".exe");
|
return Path.ChangeExtension(entryPointFilename, ".exe");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Path.Join(commandLineArguments.OutputDirectory, commandLineArguments.OutputFileName);
|
return Path.Combine(commandLineArguments.OutputDirectory, commandLineArguments.OutputFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int LogDiagnostics()
|
private int LogDiagnostics()
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ namespace Semmle.Extraction.CSharp
|
|||||||
* Although GetRandomFileName() is cryptographically secure,
|
* Although GetRandomFileName() is cryptographically secure,
|
||||||
* there's a tiny chance the file could already exists.
|
* there's a tiny chance the file could already exists.
|
||||||
*/
|
*/
|
||||||
tmpFile = Path.Join(tempPath, Path.GetRandomFileName());
|
tmpFile = Path.Combine(tempPath, Path.GetRandomFileName());
|
||||||
}
|
}
|
||||||
while (File.Exists(tmpFile));
|
while (File.Exists(tmpFile));
|
||||||
|
|
||||||
|
|||||||
@@ -82,13 +82,13 @@ namespace SemmleTests.Semmle.Util
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void CanonicalPathMissingFile()
|
public void CanonicalPathMissingFile()
|
||||||
{
|
{
|
||||||
Assert.Equal(Path.Join(Directory.GetCurrentDirectory(), "NOSUCHFILE"), cache.GetCanonicalPath("NOSUCHFILE"));
|
Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), "NOSUCHFILE"), cache.GetCanonicalPath("NOSUCHFILE"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CanonicalPathMissingAbsolutePath()
|
public void CanonicalPathMissingAbsolutePath()
|
||||||
{
|
{
|
||||||
Assert.Equal(Path.Join(root, "no", "such", "file"), cache.GetCanonicalPath(Path.Join(root, "no", "such", "file")));
|
Assert.Equal(Path.Combine(root, "no", "such", "file"), cache.GetCanonicalPath(Path.Combine(root, "no", "such", "file")));
|
||||||
|
|
||||||
if (Win32.IsWindows())
|
if (Win32.IsWindows())
|
||||||
Assert.Equal(@"C:\Windows\no\such\file", cache.GetCanonicalPath(@"C:\windOws\no\such\file"));
|
Assert.Equal(@"C:\Windows\no\such\file", cache.GetCanonicalPath(@"C:\windOws\no\such\file"));
|
||||||
@@ -97,7 +97,7 @@ namespace SemmleTests.Semmle.Util
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void CanonicalPathMissingRelativePath()
|
public void CanonicalPathMissingRelativePath()
|
||||||
{
|
{
|
||||||
Assert.Equal(Path.Join(Directory.GetCurrentDirectory(), "NO", "SUCH"), cache.GetCanonicalPath(Path.Join("NO", "SUCH")));
|
Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), "NO", "SUCH"), cache.GetCanonicalPath(Path.Combine("NO", "SUCH")));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -125,7 +125,7 @@ namespace SemmleTests.Semmle.Util
|
|||||||
public void CanonicalPathDots()
|
public void CanonicalPathDots()
|
||||||
{
|
{
|
||||||
var abcPath = Path.GetFullPath("abc");
|
var abcPath = Path.GetFullPath("abc");
|
||||||
Assert.Equal(abcPath, cache.GetCanonicalPath(Path.Join("foo", ".", "..", "abc")));
|
Assert.Equal(abcPath, cache.GetCanonicalPath(Path.Combine("foo", ".", "..", "abc")));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
@@ -14,20 +14,20 @@ namespace SemmleTests.Semmle.Util
|
|||||||
public sealed class LongPaths
|
public sealed class LongPaths
|
||||||
{
|
{
|
||||||
private static readonly string tmpDir = Environment.GetEnvironmentVariable("TEST_TMPDIR") ?? Path.GetTempPath();
|
private static readonly string tmpDir = Environment.GetEnvironmentVariable("TEST_TMPDIR") ?? Path.GetTempPath();
|
||||||
private static readonly string longPathDir = Path.Join(tmpDir, "aaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
private static readonly string longPathDir = Path.Combine(tmpDir, "aaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
||||||
"ccccccccccccccccccccccccccccccc", "ddddddddddddddddddddddddddddddddddddd", "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "fffffffffffffffffffffffffffffffff",
|
"ccccccccccccccccccccccccccccccc", "ddddddddddddddddddddddddddddddddddddd", "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "fffffffffffffffffffffffffffffffff",
|
||||||
"ggggggggggggggggggggggggggggggggggg", "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh");
|
"ggggggggggggggggggggggggggggggggggg", "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh");
|
||||||
|
|
||||||
private static string MakeLongPath()
|
private static string MakeLongPath()
|
||||||
{
|
{
|
||||||
var uniquePostfix = Guid.NewGuid().ToString("N");
|
var uniquePostfix = Guid.NewGuid().ToString("N");
|
||||||
return Path.Join(longPathDir, $"iiiiiiiiiiiiiiii{uniquePostfix}.txt");
|
return Path.Combine(longPathDir, $"iiiiiiiiiiiiiiii{uniquePostfix}.txt");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string MakeShortPath()
|
private static string MakeShortPath()
|
||||||
{
|
{
|
||||||
var uniquePostfix = Guid.NewGuid().ToString("N");
|
var uniquePostfix = Guid.NewGuid().ToString("N");
|
||||||
return Path.Join(tmpDir, $"test{uniquePostfix}.txt");
|
return Path.Combine(tmpDir, $"test{uniquePostfix}.txt");
|
||||||
}
|
}
|
||||||
|
|
||||||
public LongPaths()
|
public LongPaths()
|
||||||
@@ -62,7 +62,7 @@ namespace SemmleTests.Semmle.Util
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void ParentDirectory()
|
public void ParentDirectory()
|
||||||
{
|
{
|
||||||
Assert.Equal("abc", Path.GetDirectoryName(Path.Join("abc", "def")));
|
Assert.Equal("abc", Path.GetDirectoryName(Path.Combine("abc", "def")));
|
||||||
Assert.Equal(Win32.IsWindows() ? "\\" : "/", Path.GetDirectoryName($@"{Path.DirectorySeparatorChar}def"));
|
Assert.Equal(Win32.IsWindows() ? "\\" : "/", Path.GetDirectoryName($@"{Path.DirectorySeparatorChar}def"));
|
||||||
Assert.Equal("", Path.GetDirectoryName(@"def"));
|
Assert.Equal("", Path.GetDirectoryName(@"def"));
|
||||||
|
|
||||||
|
|||||||
@@ -137,11 +137,11 @@ namespace Semmle.Util
|
|||||||
bool IsMonoInstalled();
|
bool IsMonoInstalled();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Joins path segments, Path.Join().
|
/// Combine path segments, Path.Combine().
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="parts">The parts of the path.</param>
|
/// <param name="parts">The parts of the path.</param>
|
||||||
/// <returns>The combined path.</returns>
|
/// <returns>The combined path.</returns>
|
||||||
string PathJoin(params string[] parts);
|
string PathCombine(params string[] parts);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the full path for <paramref name="path"/>, Path.GetFullPath().
|
/// Gets the full path for <paramref name="path"/>, Path.GetFullPath().
|
||||||
@@ -293,7 +293,7 @@ namespace Semmle.Util
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string IBuildActions.PathJoin(params string[] parts) => Path.Join(parts);
|
string IBuildActions.PathCombine(params string[] parts) => Path.Combine(parts);
|
||||||
|
|
||||||
void IBuildActions.WriteAllText(string filename, string contents) => File.WriteAllText(filename, contents);
|
void IBuildActions.WriteAllText(string filename, string contents) => File.WriteAllText(filename, contents);
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace Semmle.Util
|
|||||||
var parent = Directory.GetParent(path);
|
var parent = Directory.GetParent(path);
|
||||||
|
|
||||||
return parent is not null ?
|
return parent is not null ?
|
||||||
Path.Join(cache.GetCanonicalPath(parent.FullName), Path.GetFileName(path)) :
|
Path.Combine(cache.GetCanonicalPath(parent.FullName), Path.GetFileName(path)) :
|
||||||
path.ToUpperInvariant();
|
path.ToUpperInvariant();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,12 +138,12 @@ namespace Semmle.Util
|
|||||||
var entries = Directory.GetFileSystemEntries(parentPath, name);
|
var entries = Directory.GetFileSystemEntries(parentPath, name);
|
||||||
return entries.Length == 1
|
return entries.Length == 1
|
||||||
? entries[0]
|
? entries[0]
|
||||||
: Path.Join(parentPath, name);
|
: Path.Combine(parentPath, name);
|
||||||
}
|
}
|
||||||
catch // lgtm[cs/catch-of-all-exceptions]
|
catch // lgtm[cs/catch-of-all-exceptions]
|
||||||
{
|
{
|
||||||
// IO error or security error querying directory.
|
// IO error or security error querying directory.
|
||||||
return Path.Join(parentPath, name);
|
return Path.Combine(parentPath, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ namespace Semmle.Util
|
|||||||
{
|
{
|
||||||
exes = new[] { prog };
|
exes = new[] { prog };
|
||||||
}
|
}
|
||||||
var candidates = paths?.Where(path => exes.Any(exe0 => File.Exists(Path.Join(path, exe0))));
|
var candidates = paths?.Where(path => exes.Any(exe0 => File.Exists(Path.Combine(path, exe0))));
|
||||||
return candidates?.FirstOrDefault();
|
return candidates?.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ namespace Semmle.Util
|
|||||||
{
|
{
|
||||||
innerpath = ConvertPathToSafeRelativePath(innerpath);
|
innerpath = ConvertPathToSafeRelativePath(innerpath);
|
||||||
|
|
||||||
nested = Path.Join(outerpath, innerpath);
|
nested = Path.Combine(outerpath, innerpath);
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -203,7 +203,7 @@ namespace Semmle.Util
|
|||||||
{
|
{
|
||||||
var tempPath = Path.GetTempPath();
|
var tempPath = Path.GetTempPath();
|
||||||
var name = Guid.NewGuid().ToString("N").ToUpper();
|
var name = Guid.NewGuid().ToString("N").ToUpper();
|
||||||
var tempFolder = Path.Join(tempPath, "GitHub", name);
|
var tempFolder = Path.Combine(tempPath, "GitHub", name);
|
||||||
Directory.CreateDirectory(tempFolder);
|
Directory.CreateDirectory(tempFolder);
|
||||||
return tempFolder;
|
return tempFolder;
|
||||||
});
|
});
|
||||||
@@ -231,7 +231,7 @@ namespace Semmle.Util
|
|||||||
string outputPath;
|
string outputPath;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
outputPath = Path.Join(tempFolder, Path.GetRandomFileName() + extension);
|
outputPath = Path.Combine(tempFolder, Path.GetRandomFileName() + extension);
|
||||||
}
|
}
|
||||||
while (File.Exists(outputPath));
|
while (File.Exists(outputPath));
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
category: minorAnalysis
|
|
||||||
---
|
|
||||||
* Improved extraction of range-access expressions on spans and strings (for example, `a[0..3]`). These expressions are now extracted as `Slice` (span) or `Substring` (string) calls.
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
category: minorAnalysis
|
|
||||||
---
|
|
||||||
* Improved property and indexer call target resolution for partially overridden properties and indexers.
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
category: majorAnalysis
|
|
||||||
---
|
|
||||||
* Added Razor Page handler method parameters (e.g., `OnGet`, `OnPost`, `OnPostAsync`) as remote flow sources, enabling security queries such as `cs/sql-injection` to detect vulnerabilities in `PageModel` subclasses.
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
category: breaking
|
|
||||||
---
|
|
||||||
* Renamed types related to *operation* expressions. The QL classes `BinaryArithmeticOperation`, `BinaryBitwiseOperation`, and `BinaryLogicalOperation` now include compound assignments; for example, `BinaryArithmeticOperation` now includes `a += b`.
|
|
||||||
@@ -50,15 +50,15 @@ private predicate maybeUsedInElfHashFunction(Variable v, Operation xor, Operatio
|
|||||||
|
|
|
|
||||||
add instanceof AddOperation and
|
add instanceof AddOperation and
|
||||||
e1.getAChild*() = add.getAnOperand() and
|
e1.getAChild*() = add.getAnOperand() and
|
||||||
e1 instanceof BinaryBitwiseExpr and
|
e1 instanceof BinaryBitwiseOperation and
|
||||||
e2 = e1.(BinaryBitwiseExpr).getLeftOperand() and
|
e2 = e1.(BinaryBitwiseOperation).getLeftOperand() and
|
||||||
v = addAssign.getTargetVariable() and
|
v = addAssign.getTargetVariable() and
|
||||||
addAssign.getAChild*() = add and
|
addAssign.getAChild*() = add and
|
||||||
(xor instanceof BitwiseXorExpr or xor instanceof AssignXorExpr) and
|
(xor instanceof BitwiseXorExpr or xor instanceof AssignXorExpr) and
|
||||||
addAssign.getControlFlowNode().getASuccessor*() = xor.getControlFlowNode() and
|
addAssign.getControlFlowNode().getASuccessor*() = xor.getControlFlowNode() and
|
||||||
xorAssign.getAChild*() = xor and
|
xorAssign.getAChild*() = xor and
|
||||||
v = xorAssign.getTargetVariable() and
|
v = xorAssign.getTargetVariable() and
|
||||||
(notOp instanceof UnaryBitwiseOperation or notOp instanceof AssignBitwiseExpr) and
|
(notOp instanceof UnaryBitwiseOperation or notOp instanceof AssignBitwiseOperation) and
|
||||||
xor.getControlFlowNode().getASuccessor*() = notOp.getControlFlowNode() and
|
xor.getControlFlowNode().getASuccessor*() = notOp.getControlFlowNode() and
|
||||||
notAssign.getAChild*() = notOp and
|
notAssign.getAChild*() = notOp and
|
||||||
v = notAssign.getTargetVariable() and
|
v = notAssign.getTargetVariable() and
|
||||||
|
|||||||
@@ -290,7 +290,7 @@ module AssignableInternal {
|
|||||||
newtype TAssignableDefinition =
|
newtype TAssignableDefinition =
|
||||||
TAssignmentDefinition(Assignment a) {
|
TAssignmentDefinition(Assignment a) {
|
||||||
not a.getLeftOperand() instanceof TupleExpr and
|
not a.getLeftOperand() instanceof TupleExpr and
|
||||||
not a instanceof AssignCallExpr and
|
not a instanceof AssignCallOperation and
|
||||||
not a instanceof AssignCoalesceExpr
|
not a instanceof AssignCoalesceExpr
|
||||||
} or
|
} or
|
||||||
TTupleAssignmentDefinition(AssignExpr ae, Expr leaf) { tupleAssignmentDefinition(ae, leaf) } or
|
TTupleAssignmentDefinition(AssignExpr ae, Expr leaf) { tupleAssignmentDefinition(ae, leaf) } or
|
||||||
@@ -324,7 +324,7 @@ module AssignableInternal {
|
|||||||
TAddressOfDefinition(AddressOfExpr aoe) or
|
TAddressOfDefinition(AddressOfExpr aoe) or
|
||||||
TPatternDefinition(TopLevelPatternDecl tlpd) or
|
TPatternDefinition(TopLevelPatternDecl tlpd) or
|
||||||
TAssignOperationDefinition(AssignOperation ao) {
|
TAssignOperationDefinition(AssignOperation ao) {
|
||||||
ao instanceof AssignCallExpr and not ao instanceof CompoundAssignmentOperatorCall
|
ao instanceof AssignCallOperation and not ao instanceof CompoundAssignmentOperatorCall
|
||||||
or
|
or
|
||||||
ao instanceof AssignCoalesceExpr
|
ao instanceof AssignCoalesceExpr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,13 +121,6 @@ private module Cached {
|
|||||||
result = getAChildExpr(parent)
|
result = getAChildExpr(parent)
|
||||||
or
|
or
|
||||||
result = parent.getAChildStmt()
|
result = parent.getAChildStmt()
|
||||||
or
|
|
||||||
result =
|
|
||||||
any(TypeMention tm |
|
|
||||||
tm.getTarget() = parent
|
|
||||||
or
|
|
||||||
tm.getParent+().getTarget() = parent
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate parent(ControlFlowElement child, ExprOrStmtParent parent) {
|
private predicate parent(ControlFlowElement child, ExprOrStmtParent parent) {
|
||||||
|
|||||||
@@ -57,28 +57,6 @@ class DeclarationWithGetSetAccessors extends DeclarationWithAccessors, TopLevelE
|
|||||||
/** Gets the `set` accessor of this declaration, if any. */
|
/** Gets the `set` accessor of this declaration, if any. */
|
||||||
Setter getSetter() { result = this.getAnAccessor() }
|
Setter getSetter() { result = this.getAnAccessor() }
|
||||||
|
|
||||||
/** Gets the target accessor of this declaration when used in a read context, if any. */
|
|
||||||
Accessor getReadTarget() {
|
|
||||||
result = this.getGetter()
|
|
||||||
or
|
|
||||||
not exists(this.getGetter()) and
|
|
||||||
result = this.getOverridee().getReadTarget()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets the target accessor of this declaration when used in a write context, if any. */
|
|
||||||
Accessor getWriteTarget() {
|
|
||||||
result = this.getSetter()
|
|
||||||
or
|
|
||||||
not exists(this.getSetter()) and
|
|
||||||
result = this.getOverridee().getWriteTarget()
|
|
||||||
or
|
|
||||||
result =
|
|
||||||
any(Getter g |
|
|
||||||
g = this.getReadTarget() and
|
|
||||||
g.getAnnotatedReturnType().isRef()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override DeclarationWithGetSetAccessors getOverridee() {
|
override DeclarationWithGetSetAccessors getOverridee() {
|
||||||
result = DeclarationWithAccessors.super.getOverridee()
|
result = DeclarationWithAccessors.super.getOverridee()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import Generics
|
|||||||
import Location
|
import Location
|
||||||
import Namespace
|
import Namespace
|
||||||
import Property
|
import Property
|
||||||
import semmle.code.csharp.controlflow.ControlFlowElement
|
|
||||||
private import Conversion
|
private import Conversion
|
||||||
private import semmle.code.csharp.metrics.Coupling
|
private import semmle.code.csharp.metrics.Coupling
|
||||||
private import TypeRef
|
private import TypeRef
|
||||||
@@ -1287,7 +1286,7 @@ class TupleType extends ValueType, @tuple_type {
|
|||||||
* A type mention, that is, any mention of a type in a source code file.
|
* A type mention, that is, any mention of a type in a source code file.
|
||||||
* For example, `int` is mentioned in `int M() { return 1; }`.
|
* For example, `int` is mentioned in `int M() { return 1; }`.
|
||||||
*/
|
*/
|
||||||
class TypeMention extends ControlFlowElement, @type_mention {
|
class TypeMention extends @type_mention {
|
||||||
Type type;
|
Type type;
|
||||||
@type_mention_parent parent;
|
@type_mention_parent parent;
|
||||||
|
|
||||||
@@ -1320,13 +1319,13 @@ class TypeMention extends ControlFlowElement, @type_mention {
|
|||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
override TypeMention getParent() { result = parent }
|
TypeMention getParent() { result = parent }
|
||||||
|
|
||||||
/** Gets a textual representation of this type mention. */
|
/** Gets a textual representation of this type mention. */
|
||||||
override string toString() { result = type.toString() }
|
string toString() { result = type.toString() }
|
||||||
|
|
||||||
/** Gets the location of this type mention. */
|
/** Gets the location of this type mention. */
|
||||||
override Location getALocation() { type_mention_location(this, result) }
|
Location getLocation() { type_mention_location(this, result) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class ControlFlowElementOrCallable extends ExprOrStmtParent, TControlFlowElement
|
|||||||
*/
|
*/
|
||||||
class ControlFlowElement extends ControlFlowElementOrCallable, @control_flow_element {
|
class ControlFlowElement extends ControlFlowElementOrCallable, @control_flow_element {
|
||||||
/** Gets the enclosing callable of this element, if any. */
|
/** Gets the enclosing callable of this element, if any. */
|
||||||
Callable getEnclosingCallable() { enclosingCallable(this, result) }
|
Callable getEnclosingCallable() { none() }
|
||||||
|
|
||||||
/** Gets the assembly that this element was compiled into. */
|
/** Gets the assembly that this element was compiled into. */
|
||||||
Assembly getAssembly() {
|
Assembly getAssembly() {
|
||||||
|
|||||||
@@ -912,17 +912,18 @@ module Internal {
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
// In C#, `null + 1` has type `int?` with value `null`
|
// In C#, `null + 1` has type `int?` with value `null`
|
||||||
result =
|
exists(BinaryOperation bo, Expr o |
|
||||||
any(BinaryArithmeticOperation bao |
|
bo instanceof BinaryArithmeticOperation or
|
||||||
exists(Expr o |
|
bo instanceof AssignArithmeticOperation
|
||||||
bao.getAnOperand() = e and
|
|
|
||||||
bao.getAnOperand() = o and
|
result = bo and
|
||||||
|
bo.getAnOperand() = e and
|
||||||
|
bo.getAnOperand() = o and
|
||||||
// The other operand must be provably non-null in order
|
// The other operand must be provably non-null in order
|
||||||
// for `only if` to hold
|
// for `only if` to hold
|
||||||
nonNullValueImplied(o) and
|
nonNullValueImplied(o) and
|
||||||
e != o
|
e != o
|
||||||
)
|
)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -933,10 +934,10 @@ module Internal {
|
|||||||
any(QualifiableExpr qe |
|
any(QualifiableExpr qe |
|
||||||
qe.isConditional() and
|
qe.isConditional() and
|
||||||
result = qe.getQualifier()
|
result = qe.getQualifier()
|
||||||
)
|
) or
|
||||||
or
|
|
||||||
// In C#, `null + 1` has type `int?` with value `null`
|
// In C#, `null + 1` has type `int?` with value `null`
|
||||||
e = any(BinaryArithmeticOperation bao | result = bao.getAnOperand())
|
e = any(BinaryArithmeticOperation bao | result = bao.getAnOperand()) or
|
||||||
|
e = any(AssignArithmeticOperation aao | result = aao.getAnOperand())
|
||||||
}
|
}
|
||||||
|
|
||||||
deprecated predicate isGuard(Expr e, GuardValue val) {
|
deprecated predicate isGuard(Expr e, GuardValue val) {
|
||||||
|
|||||||
@@ -145,8 +145,6 @@ module Ast implements AstSig<Location> {
|
|||||||
final private class ParameterFinal = CS::Parameter;
|
final private class ParameterFinal = CS::Parameter;
|
||||||
|
|
||||||
class Parameter extends ParameterFinal {
|
class Parameter extends ParameterFinal {
|
||||||
AstNode getPattern() { result = this }
|
|
||||||
|
|
||||||
Expr getDefaultValue() {
|
Expr getDefaultValue() {
|
||||||
// Avoid combinatorial explosions for callables with multiple bodies
|
// Avoid combinatorial explosions for callables with multiple bodies
|
||||||
result = unique( | | super.getDefaultValue())
|
result = unique( | | super.getDefaultValue())
|
||||||
@@ -174,10 +172,6 @@ module Ast implements AstSig<Location> {
|
|||||||
|
|
||||||
class DoStmt = CS::DoStmt;
|
class DoStmt = CS::DoStmt;
|
||||||
|
|
||||||
class UntilStmt extends LoopStmt {
|
|
||||||
UntilStmt() { none() }
|
|
||||||
}
|
|
||||||
|
|
||||||
final private class FinalForStmt = CS::ForStmt;
|
final private class FinalForStmt = CS::ForStmt;
|
||||||
|
|
||||||
class ForStmt extends FinalForStmt {
|
class ForStmt extends FinalForStmt {
|
||||||
@@ -209,7 +203,7 @@ module Ast implements AstSig<Location> {
|
|||||||
final private class FinalTryStmt = CS::TryStmt;
|
final private class FinalTryStmt = CS::TryStmt;
|
||||||
|
|
||||||
class TryStmt extends FinalTryStmt {
|
class TryStmt extends FinalTryStmt {
|
||||||
AstNode getBody(int index) { index = 0 and result = this.getBlock() }
|
Stmt getBody() { result = this.getBlock() }
|
||||||
|
|
||||||
CatchClause getCatch(int index) { result = this.getCatchClause(index) }
|
CatchClause getCatch(int index) { result = this.getCatchClause(index) }
|
||||||
|
|
||||||
|
|||||||
@@ -124,7 +124,9 @@ private module Internal {
|
|||||||
TDispatchDynamicOperatorCall(DynamicOperatorCall doc) or
|
TDispatchDynamicOperatorCall(DynamicOperatorCall doc) or
|
||||||
TDispatchDynamicMemberAccess(DynamicMemberAccess dma) or
|
TDispatchDynamicMemberAccess(DynamicMemberAccess dma) or
|
||||||
TDispatchDynamicElementAccess(DynamicElementAccess dea) or
|
TDispatchDynamicElementAccess(DynamicElementAccess dea) or
|
||||||
TDispatchDynamicEventAccess(AssignArithmeticExpr aao, DynamicMemberAccess dma, string name) {
|
TDispatchDynamicEventAccess(
|
||||||
|
AssignArithmeticOperation aao, DynamicMemberAccess dma, string name
|
||||||
|
) {
|
||||||
isPotentialEventCall(aao, dma, name)
|
isPotentialEventCall(aao, dma, name)
|
||||||
} or
|
} or
|
||||||
TDispatchDynamicObjectCreation(DynamicObjectCreation doc) or
|
TDispatchDynamicObjectCreation(DynamicObjectCreation doc) or
|
||||||
@@ -228,7 +230,7 @@ private module Internal {
|
|||||||
* accessor.
|
* accessor.
|
||||||
*/
|
*/
|
||||||
private predicate isPotentialEventCall(
|
private predicate isPotentialEventCall(
|
||||||
AssignArithmeticExpr aao, DynamicMemberAccess dma, string name
|
AssignArithmeticOperation aao, DynamicMemberAccess dma, string name
|
||||||
) {
|
) {
|
||||||
aao instanceof DynamicOperatorCall and
|
aao instanceof DynamicOperatorCall and
|
||||||
dma = aao.getLeftOperand() and
|
dma = aao.getLeftOperand() and
|
||||||
@@ -1395,7 +1397,9 @@ private module Internal {
|
|||||||
private class DispatchDynamicEventAccess extends DispatchReflectionOrDynamicCall,
|
private class DispatchDynamicEventAccess extends DispatchReflectionOrDynamicCall,
|
||||||
TDispatchDynamicEventAccess
|
TDispatchDynamicEventAccess
|
||||||
{
|
{
|
||||||
override AssignArithmeticExpr getCall() { this = TDispatchDynamicEventAccess(result, _, _) }
|
override AssignArithmeticOperation getCall() {
|
||||||
|
this = TDispatchDynamicEventAccess(result, _, _)
|
||||||
|
}
|
||||||
|
|
||||||
override string getName() { this = TDispatchDynamicEventAccess(_, _, result) }
|
override string getName() { this = TDispatchDynamicEventAccess(_, _, result) }
|
||||||
|
|
||||||
|
|||||||
@@ -11,27 +11,19 @@ import Expr
|
|||||||
* (`UnaryArithmeticOperation`) or a binary arithmetic operation
|
* (`UnaryArithmeticOperation`) or a binary arithmetic operation
|
||||||
* (`BinaryArithmeticOperation`).
|
* (`BinaryArithmeticOperation`).
|
||||||
*/
|
*/
|
||||||
class ArithmeticOperation extends Operation, @arith_operation {
|
class ArithmeticOperation extends Operation, @arith_op_expr {
|
||||||
override string getOperator() { none() }
|
override string getOperator() { none() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A binary arithmetic operation. Either a binary arithmetic expression (`BinaryArithmeticExpr`) or
|
* A unary arithmetic operation. Either a unary minus operation
|
||||||
* an arithmetic assignment expression (`AssignArithmeticExpr`).
|
* (`UnaryMinusExpr`), a unary plus operation (`UnaryPlusExpr`),
|
||||||
*/
|
|
||||||
class BinaryArithmeticOperation extends ArithmeticOperation, BinaryOperation, @bin_arith_operation {
|
|
||||||
override string getOperator() { none() }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A unary arithmetic operation. Either a unary minus expression
|
|
||||||
* (`UnaryMinusExpr`), a unary plus expression (`UnaryPlusExpr`),
|
|
||||||
* or a mutator operation (`MutatorOperation`).
|
* or a mutator operation (`MutatorOperation`).
|
||||||
*/
|
*/
|
||||||
class UnaryArithmeticOperation extends ArithmeticOperation, UnaryOperation, @un_arith_operation { }
|
class UnaryArithmeticOperation extends ArithmeticOperation, UnaryOperation, @un_arith_op_expr { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A unary minus expression, for example `-x`.
|
* A unary minus operation, for example `-x`.
|
||||||
*/
|
*/
|
||||||
class UnaryMinusExpr extends UnaryArithmeticOperation, @minus_expr {
|
class UnaryMinusExpr extends UnaryArithmeticOperation, @minus_expr {
|
||||||
override string getOperator() { result = "-" }
|
override string getOperator() { result = "-" }
|
||||||
@@ -40,7 +32,7 @@ class UnaryMinusExpr extends UnaryArithmeticOperation, @minus_expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A unary plus expression, for example `+x`.
|
* A unary plus operation, for example `+x`.
|
||||||
*/
|
*/
|
||||||
class UnaryPlusExpr extends UnaryArithmeticOperation, @plus_expr {
|
class UnaryPlusExpr extends UnaryArithmeticOperation, @plus_expr {
|
||||||
override string getOperator() { result = "+" }
|
override string getOperator() { result = "+" }
|
||||||
@@ -52,40 +44,40 @@ class UnaryPlusExpr extends UnaryArithmeticOperation, @plus_expr {
|
|||||||
* A mutator operation. Either an increment operation (`IncrementOperation`)
|
* A mutator operation. Either an increment operation (`IncrementOperation`)
|
||||||
* or a decrement operation (`DecrementOperation`).
|
* or a decrement operation (`DecrementOperation`).
|
||||||
*/
|
*/
|
||||||
class MutatorOperation extends UnaryArithmeticOperation, @mut_operation { }
|
class MutatorOperation extends UnaryArithmeticOperation, @mut_op_expr { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An increment operation. Either a postfix increment expression
|
* An increment operation. Either a postfix increment operation
|
||||||
* (`PostIncrExpr`) or a prefix increment expression (`PreIncrExpr`).
|
* (`PostIncrExpr`) or a prefix increment operation (`PreIncrExpr`).
|
||||||
*/
|
*/
|
||||||
class IncrementOperation extends MutatorOperation, @incr_operation {
|
class IncrementOperation extends MutatorOperation, @incr_op_expr {
|
||||||
override string getOperator() { result = "++" }
|
override string getOperator() { result = "++" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A decrement operation. Either a postfix decrement expression
|
* A decrement operation. Either a postfix decrement operation
|
||||||
* (`PostDecrExpr`) or a prefix decrement expression (`PreDecrExpr`).
|
* (`PostDecrExpr`) or a prefix decrement operation (`PreDecrExpr`).
|
||||||
*/
|
*/
|
||||||
class DecrementOperation extends MutatorOperation, @decr_operation {
|
class DecrementOperation extends MutatorOperation, @decr_op_expr {
|
||||||
override string getOperator() { result = "--" }
|
override string getOperator() { result = "--" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A prefix increment expression, for example `++x`.
|
* A prefix increment operation, for example `++x`.
|
||||||
*/
|
*/
|
||||||
class PreIncrExpr extends IncrementOperation, @pre_incr_expr {
|
class PreIncrExpr extends IncrementOperation, @pre_incr_expr {
|
||||||
override string getAPrimaryQlClass() { result = "PreIncrExpr" }
|
override string getAPrimaryQlClass() { result = "PreIncrExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A prefix decrement expression, for example `--x`.
|
* A prefix decrement operation, for example `--x`.
|
||||||
*/
|
*/
|
||||||
class PreDecrExpr extends DecrementOperation, @pre_decr_expr {
|
class PreDecrExpr extends DecrementOperation, @pre_decr_expr {
|
||||||
override string getAPrimaryQlClass() { result = "PreDecrExpr" }
|
override string getAPrimaryQlClass() { result = "PreDecrExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A postfix increment expression, for example `x++`.
|
* A postfix increment operation, for example `x++`.
|
||||||
*/
|
*/
|
||||||
class PostIncrExpr extends IncrementOperation, @post_incr_expr {
|
class PostIncrExpr extends IncrementOperation, @post_incr_expr {
|
||||||
override string toString() { result = "..." + this.getOperator() }
|
override string toString() { result = "..." + this.getOperator() }
|
||||||
@@ -94,7 +86,7 @@ class PostIncrExpr extends IncrementOperation, @post_incr_expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A postfix decrement expression, for example `x--`.
|
* A postfix decrement operation, for example `x--`.
|
||||||
*/
|
*/
|
||||||
class PostDecrExpr extends DecrementOperation, @post_decr_expr {
|
class PostDecrExpr extends DecrementOperation, @post_decr_expr {
|
||||||
override string toString() { result = "..." + this.getOperator() }
|
override string toString() { result = "..." + this.getOperator() }
|
||||||
@@ -103,84 +95,55 @@ class PostDecrExpr extends DecrementOperation, @post_decr_expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An addition operation, either `x + y` or `x += y`.
|
* A binary arithmetic operation. Either an addition operation
|
||||||
|
* (`AddExpr`), a subtraction operation (`SubExpr`), a multiplication
|
||||||
|
* operation (`MulExpr`), a division operation (`DivExpr`), or a
|
||||||
|
* remainder operation (`RemExpr`).
|
||||||
*/
|
*/
|
||||||
class AddOperation extends BinaryArithmeticOperation, @add_operation { }
|
class BinaryArithmeticOperation extends ArithmeticOperation, BinaryOperation, @bin_arith_op_expr {
|
||||||
|
override string getOperator() { none() }
|
||||||
/**
|
|
||||||
* A subtraction operation, either `x - y` or `x -= y`.
|
|
||||||
*/
|
|
||||||
class SubOperation extends BinaryArithmeticOperation, @sub_operation { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A multiplication operation, either `x * y` or `x *= y`.
|
|
||||||
*/
|
|
||||||
class MulOperation extends BinaryArithmeticOperation, @mul_operation { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A division operation, either `x / y` or `x /= y`.
|
|
||||||
*/
|
|
||||||
class DivOperation extends BinaryArithmeticOperation, @div_operation {
|
|
||||||
/** Gets the numerator of this division operation. */
|
|
||||||
Expr getNumerator() { result = this.getLeftOperand() }
|
|
||||||
|
|
||||||
/** Gets the denominator of this division operation. */
|
|
||||||
Expr getDenominator() { result = this.getRightOperand() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A remainder operation, either `x % y` or `x %= y`.
|
* An addition operation, for example `x + y`.
|
||||||
*/
|
*/
|
||||||
class RemOperation extends BinaryArithmeticOperation, @rem_operation { }
|
class AddExpr extends BinaryArithmeticOperation, AddOperation, @add_expr {
|
||||||
|
|
||||||
/**
|
|
||||||
* A binary arithmetic expression. Either an addition expression
|
|
||||||
* (`AddExpr`), a subtraction expression (`SubExpr`), a multiplication
|
|
||||||
* expression (`MulExpr`), a division expression (`DivExpr`), or a
|
|
||||||
* remainder expression (`RemExpr`).
|
|
||||||
*/
|
|
||||||
class BinaryArithmeticExpr extends BinaryArithmeticOperation, @bin_arith_expr { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An addition expression, for example `x + y`.
|
|
||||||
*/
|
|
||||||
class AddExpr extends BinaryArithmeticExpr, AddOperation, @add_expr {
|
|
||||||
override string getOperator() { result = "+" }
|
override string getOperator() { result = "+" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "AddExpr" }
|
override string getAPrimaryQlClass() { result = "AddExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A subtraction expression, for example `x - y`.
|
* A subtraction operation, for example `x - y`.
|
||||||
*/
|
*/
|
||||||
class SubExpr extends BinaryArithmeticExpr, SubOperation, @sub_expr {
|
class SubExpr extends BinaryArithmeticOperation, SubOperation, @sub_expr {
|
||||||
override string getOperator() { result = "-" }
|
override string getOperator() { result = "-" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "SubExpr" }
|
override string getAPrimaryQlClass() { result = "SubExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A multiplication expression, for example `x * y`.
|
* A multiplication operation, for example `x * y`.
|
||||||
*/
|
*/
|
||||||
class MulExpr extends BinaryArithmeticExpr, MulOperation, @mul_expr {
|
class MulExpr extends BinaryArithmeticOperation, MulOperation, @mul_expr {
|
||||||
override string getOperator() { result = "*" }
|
override string getOperator() { result = "*" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "MulExpr" }
|
override string getAPrimaryQlClass() { result = "MulExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A division expression, for example `x / y`.
|
* A division operation, for example `x / y`.
|
||||||
*/
|
*/
|
||||||
class DivExpr extends BinaryArithmeticExpr, DivOperation, @div_expr {
|
class DivExpr extends BinaryArithmeticOperation, DivOperation, @div_expr {
|
||||||
override string getOperator() { result = "/" }
|
override string getOperator() { result = "/" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "DivExpr" }
|
override string getAPrimaryQlClass() { result = "DivExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A remainder expression, for example `x % y`.
|
* A remainder operation, for example `x % y`.
|
||||||
*/
|
*/
|
||||||
class RemExpr extends BinaryArithmeticExpr, RemOperation, @rem_expr {
|
class RemExpr extends BinaryArithmeticOperation, RemOperation, @rem_expr {
|
||||||
override string getOperator() { result = "%" }
|
override string getOperator() { result = "%" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "RemExpr" }
|
override string getAPrimaryQlClass() { result = "RemExpr" }
|
||||||
|
|||||||
@@ -72,9 +72,9 @@ class AssignExpr extends Assignment, @simple_assign_expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An assignment operation. Either an arithmetic assignment expression
|
* An assignment operation. Either an arithmetic assignment operation
|
||||||
* (`AssignArithmeticExpr`), a bitwise assignment expression
|
* (`AssignArithmeticOperation`), a bitwise assignment operation
|
||||||
* (`AssignBitwiseExpr`), an event assignment (`AddOrRemoveEventExpr`), or
|
* (`AssignBitwiseOperation`), an event assignment (`AddOrRemoveEventExpr`), or
|
||||||
* a null-coalescing assignment (`AssignCoalesceExpr`).
|
* a null-coalescing assignment (`AssignCoalesceExpr`).
|
||||||
*/
|
*/
|
||||||
class AssignOperation extends Assignment, @assign_op_expr {
|
class AssignOperation extends Assignment, @assign_op_expr {
|
||||||
@@ -94,147 +94,134 @@ class AssignOperation extends Assignment, @assign_op_expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A compound assignment expression that invokes an operator.
|
* A compound assignment operation that invokes an operator.
|
||||||
*
|
*
|
||||||
* (1) `x += y` invokes the compound assignment operator `+=` (if it exists).
|
* (1) `x += y` invokes the compound assignment operator `+=` (if it exists).
|
||||||
* (2) `x += y` invokes the operator `+` and assigns `x + y` to `x`.
|
* (2) `x += y` invokes the operator `+` and assigns `x + y` to `x`.
|
||||||
*
|
*
|
||||||
* Either an arithmetic assignment expression (`AssignArithmeticExpr`) or a bitwise
|
* Either an arithmetic assignment operation (`AssignArithmeticOperation`) or a bitwise
|
||||||
* assignment expression (`AssignBitwiseExpr`).
|
* assignment operation (`AssignBitwiseOperation`).
|
||||||
*/
|
*/
|
||||||
class AssignCallExpr extends AssignOperation, OperatorCall, QualifiableExpr, @assign_op_call_expr {
|
class AssignCallOperation extends AssignOperation, OperatorCall, QualifiableExpr,
|
||||||
|
@assign_op_call_expr
|
||||||
|
{
|
||||||
override string toString() { result = AssignOperation.super.toString() }
|
override string toString() { result = AssignOperation.super.toString() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DEPRECATED: Use `AssignCallExpr` instead.
|
* An arithmetic assignment operation. Either an addition assignment operation
|
||||||
*/
|
* (`AssignAddExpr`), a subtraction assignment operation (`AssignSubExpr`), a
|
||||||
deprecated class AssignCallOperation = AssignCallExpr;
|
* multiplication assignment operation (`AssignMulExpr`), a division assignment
|
||||||
|
* operation (`AssignDivExpr`), or a remainder assignment operation
|
||||||
/**
|
|
||||||
* An arithmetic assignment expression. Either an addition assignment expression
|
|
||||||
* (`AssignAddExpr`), a subtraction assignment expression (`AssignSubExpr`), a
|
|
||||||
* multiplication assignment expression (`AssignMulExpr`), a division assignment
|
|
||||||
* expression (`AssignDivExpr`), or a remainder assignment expression
|
|
||||||
* (`AssignRemExpr`).
|
* (`AssignRemExpr`).
|
||||||
*/
|
*/
|
||||||
class AssignArithmeticExpr extends AssignCallExpr, @assign_arith_expr { }
|
class AssignArithmeticOperation extends AssignCallOperation, @assign_arith_expr { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DEPRECATED: Use `AssignArithmeticExpr` instead.
|
* An addition assignment operation, for example `x += y`.
|
||||||
*/
|
*/
|
||||||
deprecated class AssignArithmeticOperation = AssignArithmeticExpr;
|
class AssignAddExpr extends AssignArithmeticOperation, AddOperation, @assign_add_expr {
|
||||||
|
|
||||||
/**
|
|
||||||
* An addition assignment expression, for example `x += y`.
|
|
||||||
*/
|
|
||||||
class AssignAddExpr extends AssignArithmeticExpr, AddOperation, @assign_add_expr {
|
|
||||||
override string getOperator() { result = "+=" }
|
override string getOperator() { result = "+=" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "AssignAddExpr" }
|
override string getAPrimaryQlClass() { result = "AssignAddExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A subtraction assignment expression, for example `x -= y`.
|
* A subtraction assignment operation, for example `x -= y`.
|
||||||
*/
|
*/
|
||||||
class AssignSubExpr extends AssignArithmeticExpr, SubOperation, @assign_sub_expr {
|
class AssignSubExpr extends AssignArithmeticOperation, SubOperation, @assign_sub_expr {
|
||||||
override string getOperator() { result = "-=" }
|
override string getOperator() { result = "-=" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "AssignSubExpr" }
|
override string getAPrimaryQlClass() { result = "AssignSubExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A multiplication assignment expression, for example `x *= y`.
|
* An multiplication assignment operation, for example `x *= y`.
|
||||||
*/
|
*/
|
||||||
class AssignMulExpr extends AssignArithmeticExpr, MulOperation, @assign_mul_expr {
|
class AssignMulExpr extends AssignArithmeticOperation, MulOperation, @assign_mul_expr {
|
||||||
override string getOperator() { result = "*=" }
|
override string getOperator() { result = "*=" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "AssignMulExpr" }
|
override string getAPrimaryQlClass() { result = "AssignMulExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A division assignment expression, for example `x /= y`.
|
* An division assignment operation, for example `x /= y`.
|
||||||
*/
|
*/
|
||||||
class AssignDivExpr extends AssignArithmeticExpr, DivOperation, @assign_div_expr {
|
class AssignDivExpr extends AssignArithmeticOperation, DivOperation, @assign_div_expr {
|
||||||
override string getOperator() { result = "/=" }
|
override string getOperator() { result = "/=" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "AssignDivExpr" }
|
override string getAPrimaryQlClass() { result = "AssignDivExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A remainder assignment expression, for example `x %= y`.
|
* A remainder assignment operation, for example `x %= y`.
|
||||||
*/
|
*/
|
||||||
class AssignRemExpr extends AssignArithmeticExpr, RemOperation, @assign_rem_expr {
|
class AssignRemExpr extends AssignArithmeticOperation, RemOperation, @assign_rem_expr {
|
||||||
override string getOperator() { result = "%=" }
|
override string getOperator() { result = "%=" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "AssignRemExpr" }
|
override string getAPrimaryQlClass() { result = "AssignRemExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A bitwise assignment expression. Either a bitwise-and assignment
|
* A bitwise assignment operation. Either a bitwise-and assignment
|
||||||
* expression (`AssignAndExpr`), a bitwise-or assignment
|
* operation (`AssignAndExpr`), a bitwise-or assignment
|
||||||
* expression (`AssignOrExpr`), a bitwise exclusive-or assignment
|
* operation (`AssignOrExpr`), a bitwise exclusive-or assignment
|
||||||
* expression (`AssignXorExpr`), a left-shift assignment
|
* operation (`AssignXorExpr`), a left-shift assignment
|
||||||
* expression (`AssignLeftShiftExpr`), or a right-shift assignment
|
* operation (`AssignLeftShiftExpr`), or a right-shift assignment
|
||||||
* expression (`AssignRightShiftExpr`), or an unsigned right-shift assignment
|
* operation (`AssignRightShiftExpr`), or an unsigned right-shift assignment
|
||||||
* expression (`AssignUnsignedRightShiftExpr`).
|
* operation (`AssignUnsignedRightShiftExpr`).
|
||||||
*/
|
*/
|
||||||
class AssignBitwiseExpr extends AssignCallExpr, @assign_bitwise_expr { }
|
class AssignBitwiseOperation extends AssignCallOperation, @assign_bitwise_expr { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DEPRECATED: Use `AssignBitwiseExpr` instead.
|
* A bitwise-and assignment operation, for example `x &= y`.
|
||||||
*/
|
*/
|
||||||
deprecated class AssignBitwiseOperation = AssignBitwiseExpr;
|
class AssignAndExpr extends AssignBitwiseOperation, BitwiseAndOperation, @assign_and_expr {
|
||||||
|
|
||||||
/**
|
|
||||||
* A bitwise-and assignment expression, for example `x &= y`.
|
|
||||||
*/
|
|
||||||
class AssignAndExpr extends AssignBitwiseExpr, BitwiseAndOperation, @assign_and_expr {
|
|
||||||
override string getOperator() { result = "&=" }
|
override string getOperator() { result = "&=" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "AssignAndExpr" }
|
override string getAPrimaryQlClass() { result = "AssignAndExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A bitwise-or assignment expression, for example `x |= y`.
|
* A bitwise-or assignment operation, for example `x |= y`.
|
||||||
*/
|
*/
|
||||||
class AssignOrExpr extends AssignBitwiseExpr, BitwiseOrOperation, @assign_or_expr {
|
class AssignOrExpr extends AssignBitwiseOperation, BitwiseOrOperation, @assign_or_expr {
|
||||||
override string getOperator() { result = "|=" }
|
override string getOperator() { result = "|=" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "AssignOrExpr" }
|
override string getAPrimaryQlClass() { result = "AssignOrExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A bitwise exclusive-or assignment expression, for example `x ^= y`.
|
* A bitwise exclusive-or assignment operation, for example `x ^= y`.
|
||||||
*/
|
*/
|
||||||
class AssignXorExpr extends AssignBitwiseExpr, BitwiseXorOperation, @assign_xor_expr {
|
class AssignXorExpr extends AssignBitwiseOperation, BitwiseXorOperation, @assign_xor_expr {
|
||||||
override string getOperator() { result = "^=" }
|
override string getOperator() { result = "^=" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "AssignXorExpr" }
|
override string getAPrimaryQlClass() { result = "AssignXorExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A left-shift assignment expression, for example `x <<= y`.
|
* A left-shift assignment operation, for example `x <<= y`.
|
||||||
*/
|
*/
|
||||||
class AssignLeftShiftExpr extends AssignBitwiseExpr, LeftShiftOperation, @assign_lshift_expr {
|
class AssignLeftShiftExpr extends AssignBitwiseOperation, LeftShiftOperation, @assign_lshift_expr {
|
||||||
override string getOperator() { result = "<<=" }
|
override string getOperator() { result = "<<=" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "AssignLeftShiftExpr" }
|
override string getAPrimaryQlClass() { result = "AssignLeftShiftExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A right-shift assignment expression, for example `x >>= y`.
|
* A right-shift assignment operation, for example `x >>= y`.
|
||||||
*/
|
*/
|
||||||
class AssignRightShiftExpr extends AssignBitwiseExpr, RightShiftOperation, @assign_rshift_expr {
|
class AssignRightShiftExpr extends AssignBitwiseOperation, RightShiftOperation, @assign_rshift_expr {
|
||||||
override string getOperator() { result = ">>=" }
|
override string getOperator() { result = ">>=" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "AssignRightShiftExpr" }
|
override string getAPrimaryQlClass() { result = "AssignRightShiftExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An unsigned right-shift assignment expression, for example `x >>>= y`.
|
* An unsigned right-shift assignment operation, for example `x >>>= y`.
|
||||||
*/
|
*/
|
||||||
class AssignUnsignedRightShiftExpr extends AssignBitwiseExpr, UnsignedRightShiftOperation,
|
class AssignUnsignedRightShiftExpr extends AssignBitwiseOperation, UnsignedRightShiftOperation,
|
||||||
@assign_urshift_expr
|
@assign_urshift_expr
|
||||||
{
|
{
|
||||||
override string getOperator() { result = ">>>=" }
|
override string getOperator() { result = ">>>=" }
|
||||||
@@ -310,10 +297,10 @@ class RemoveEventExpr extends AddOrRemoveEventExpr, @remove_event_expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A null-coalescing assignment expression, for example `x ??= y`.
|
* A null-coalescing assignment operation, for example `x ??= y`.
|
||||||
*/
|
*/
|
||||||
class AssignCoalesceExpr extends AssignOperation, NullCoalescingOperation, @assign_coalesce_expr {
|
class AssignCoalesceExpr extends AssignOperation, NullCoalescingOperation, @assign_coalesce_expr {
|
||||||
override string getOperator() { result = "??=" }
|
override string toString() { result = "... ??= ..." }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "AssignCoalesceExpr" }
|
override string getAPrimaryQlClass() { result = "AssignCoalesceExpr" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,16 +10,16 @@ import Expr
|
|||||||
* A bitwise operation. Either a unary bitwise operation (`UnaryBitwiseOperation`)
|
* A bitwise operation. Either a unary bitwise operation (`UnaryBitwiseOperation`)
|
||||||
* or a binary bitwise operation (`BinaryBitwiseOperation`).
|
* or a binary bitwise operation (`BinaryBitwiseOperation`).
|
||||||
*/
|
*/
|
||||||
class BitwiseOperation extends Operation, @bit_operation { }
|
class BitwiseOperation extends Operation, @bit_expr { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A unary bitwise operation, that is, a bitwise complement operation
|
* A unary bitwise operation, that is, a bitwise complement operation
|
||||||
* (`ComplementExpr`).
|
* (`ComplementExpr`).
|
||||||
*/
|
*/
|
||||||
class UnaryBitwiseOperation extends BitwiseOperation, UnaryOperation, @un_bit_operation { }
|
class UnaryBitwiseOperation extends BitwiseOperation, UnaryOperation, @un_bit_op_expr { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A bitwise complement expression, for example `~x`.
|
* A bitwise complement operation, for example `~x`.
|
||||||
*/
|
*/
|
||||||
class ComplementExpr extends UnaryBitwiseOperation, @bit_not_expr {
|
class ComplementExpr extends UnaryBitwiseOperation, @bit_not_expr {
|
||||||
override string getOperator() { result = "~" }
|
override string getOperator() { result = "~" }
|
||||||
@@ -28,101 +28,67 @@ class ComplementExpr extends UnaryBitwiseOperation, @bit_not_expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A binary bitwise operation. Either a binary bitwise expression (`BinaryBitwiseExpr`) or
|
* A binary bitwise operation. Either a bitwise-and operation
|
||||||
* a bitwise assignment expression (`AssignBitwiseExpr`).
|
* (`BitwiseAndExpr`), a bitwise-or operation (`BitwiseOrExpr`),
|
||||||
|
* a bitwise exclusive-or operation (`BitwiseXorExpr`), a left-shift
|
||||||
|
* operation (`LeftShiftExpr`), a right-shift operation (`RightShiftExpr`),
|
||||||
|
* or an unsigned right-shift operation (`UnsignedRightShiftExpr`).
|
||||||
*/
|
*/
|
||||||
class BinaryBitwiseOperation extends BitwiseOperation, BinaryOperation, @bin_bit_operation {
|
class BinaryBitwiseOperation extends BitwiseOperation, BinaryOperation, @bin_bit_op_expr {
|
||||||
override string getOperator() { none() }
|
override string getOperator() { none() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A bitwise-and operation, either `x & y` or `x &= y`.
|
* A left-shift operation, for example `x << y`.
|
||||||
*/
|
*/
|
||||||
class BitwiseAndOperation extends BinaryBitwiseOperation, @and_operation { }
|
class LeftShiftExpr extends BinaryBitwiseOperation, LeftShiftOperation, @lshift_expr {
|
||||||
|
|
||||||
/**
|
|
||||||
* A bitwise-or operation, either `x | y` or `x |= y`.
|
|
||||||
*/
|
|
||||||
class BitwiseOrOperation extends BinaryBitwiseOperation, @or_operation { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A bitwise exclusive-or operation, either `x ^ y` or `x ^= y`.
|
|
||||||
*/
|
|
||||||
class BitwiseXorOperation extends BinaryBitwiseOperation, @xor_operation { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A left-shift operation, either `x << y` or `x <<= y`.
|
|
||||||
*/
|
|
||||||
class LeftShiftOperation extends BinaryBitwiseOperation, @lshift_operation { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A right-shift operation, either `x >> y` or `x >>= y`.
|
|
||||||
*/
|
|
||||||
class RightShiftOperation extends BinaryBitwiseOperation, @rshift_operation { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An unsigned right-shift operation, either `x >>> y` or `x >>>= y`.
|
|
||||||
*/
|
|
||||||
class UnsignedRightShiftOperation extends BinaryBitwiseOperation, @urshift_operation { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A binary bitwise expression. Either a bitwise-and expression
|
|
||||||
* (`BitwiseAndExpr`), a bitwise-or expression (`BitwiseOrExpr`),
|
|
||||||
* a bitwise exclusive-or expression (`BitwiseXorExpr`), a left-shift
|
|
||||||
* expression (`LeftShiftExpr`), a right-shift expression (`RightShiftExpr`),
|
|
||||||
* or an unsigned right-shift expression (`UnsignedRightShiftExpr`).
|
|
||||||
*/
|
|
||||||
class BinaryBitwiseExpr extends BinaryBitwiseOperation, @bin_bit_expr { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A left-shift expression, for example `x << y`.
|
|
||||||
*/
|
|
||||||
class LeftShiftExpr extends BinaryBitwiseExpr, LeftShiftOperation, @lshift_expr {
|
|
||||||
override string getOperator() { result = "<<" }
|
override string getOperator() { result = "<<" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "LeftShiftExpr" }
|
override string getAPrimaryQlClass() { result = "LeftShiftExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A right-shift expression, for example `x >> y`.
|
* A right-shift operation, for example `x >> y`.
|
||||||
*/
|
*/
|
||||||
class RightShiftExpr extends BinaryBitwiseExpr, RightShiftOperation, @rshift_expr {
|
class RightShiftExpr extends BinaryBitwiseOperation, RightShiftOperation, @rshift_expr {
|
||||||
override string getOperator() { result = ">>" }
|
override string getOperator() { result = ">>" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "RightShiftExpr" }
|
override string getAPrimaryQlClass() { result = "RightShiftExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An unsigned right-shift expression, for example `x >>> y`.
|
* An unsigned right-shift operation, for example `x >>> y`.
|
||||||
*/
|
*/
|
||||||
class UnsignedRightShiftExpr extends BinaryBitwiseExpr, UnsignedRightShiftOperation, @urshift_expr {
|
class UnsignedRightShiftExpr extends BinaryBitwiseOperation, UnsignedRightShiftOperation,
|
||||||
|
@urshift_expr
|
||||||
|
{
|
||||||
override string getOperator() { result = ">>>" }
|
override string getOperator() { result = ">>>" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "UnsignedRightShiftExpr" }
|
override string getAPrimaryQlClass() { result = "UnsignedRightShiftExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A bitwise-and expression, for example `x & y`.
|
* A bitwise-and operation, for example `x & y`.
|
||||||
*/
|
*/
|
||||||
class BitwiseAndExpr extends BinaryBitwiseExpr, BitwiseAndOperation, @bit_and_expr {
|
class BitwiseAndExpr extends BinaryBitwiseOperation, BitwiseAndOperation, @bit_and_expr {
|
||||||
override string getOperator() { result = "&" }
|
override string getOperator() { result = "&" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "BitwiseAndExpr" }
|
override string getAPrimaryQlClass() { result = "BitwiseAndExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A bitwise-or expression, for example `x | y`.
|
* A bitwise-or operation, for example `x | y`.
|
||||||
*/
|
*/
|
||||||
class BitwiseOrExpr extends BinaryBitwiseExpr, BitwiseOrOperation, @bit_or_expr {
|
class BitwiseOrExpr extends BinaryBitwiseOperation, BitwiseOrOperation, @bit_or_expr {
|
||||||
override string getOperator() { result = "|" }
|
override string getOperator() { result = "|" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "BitwiseOrExpr" }
|
override string getAPrimaryQlClass() { result = "BitwiseOrExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A bitwise exclusive-or expression, for example `x ^ y`.
|
* A bitwise exclusive-or operation, for example `x ^ y`.
|
||||||
*/
|
*/
|
||||||
class BitwiseXorExpr extends BinaryBitwiseExpr, BitwiseXorOperation, @bit_xor_expr {
|
class BitwiseXorExpr extends BinaryBitwiseOperation, BitwiseXorOperation, @bit_xor_expr {
|
||||||
override string getOperator() { result = "^" }
|
override string getOperator() { result = "^" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "BitwiseXorExpr" }
|
override string getAPrimaryQlClass() { result = "BitwiseXorExpr" }
|
||||||
|
|||||||
@@ -609,7 +609,7 @@ class InstanceMutatorOperatorCall extends MutatorOperatorCall {
|
|||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class CompoundAssignmentOperatorCall extends AssignCallExpr {
|
class CompoundAssignmentOperatorCall extends AssignCallOperation {
|
||||||
CompoundAssignmentOperatorCall() { this.getTarget() instanceof CompoundAssignmentOperator }
|
CompoundAssignmentOperatorCall() { this.getTarget() instanceof CompoundAssignmentOperator }
|
||||||
|
|
||||||
override Expr getArgument(int i) { result = this.getChildExpr(i + 1) and i >= 0 }
|
override Expr getArgument(int i) { result = this.getChildExpr(i + 1) and i >= 0 }
|
||||||
@@ -762,12 +762,20 @@ class AccessorCall extends Call, QualifiableExpr, @call_access_expr {
|
|||||||
*/
|
*/
|
||||||
class PropertyCall extends AccessorCall, PropertyAccessExpr {
|
class PropertyCall extends AccessorCall, PropertyAccessExpr {
|
||||||
override Accessor getReadTarget() {
|
override Accessor getReadTarget() {
|
||||||
this instanceof AssignableRead and result = this.getProperty().getReadTarget()
|
this instanceof AssignableRead and result = this.getProperty().getGetter()
|
||||||
}
|
}
|
||||||
|
|
||||||
override Accessor getWriteTarget() {
|
override Accessor getWriteTarget() {
|
||||||
this instanceof AssignableWrite and
|
this instanceof AssignableWrite and
|
||||||
result = this.getProperty().getWriteTarget()
|
exists(Property p | p = this.getProperty() |
|
||||||
|
result = p.getSetter()
|
||||||
|
or
|
||||||
|
result =
|
||||||
|
any(Getter g |
|
||||||
|
g = p.getGetter() and
|
||||||
|
g.getAnnotatedReturnType().isRef()
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override Expr getArgument(int i) {
|
override Expr getArgument(int i) {
|
||||||
@@ -798,12 +806,20 @@ class PropertyCall extends AccessorCall, PropertyAccessExpr {
|
|||||||
*/
|
*/
|
||||||
class IndexerCall extends AccessorCall, IndexerAccessExpr {
|
class IndexerCall extends AccessorCall, IndexerAccessExpr {
|
||||||
override Accessor getReadTarget() {
|
override Accessor getReadTarget() {
|
||||||
this instanceof AssignableRead and result = this.getIndexer().getReadTarget()
|
this instanceof AssignableRead and result = this.getIndexer().getGetter()
|
||||||
}
|
}
|
||||||
|
|
||||||
override Accessor getWriteTarget() {
|
override Accessor getWriteTarget() {
|
||||||
this instanceof AssignableWrite and
|
this instanceof AssignableWrite and
|
||||||
result = this.getIndexer().getWriteTarget()
|
exists(Indexer i | i = this.getIndexer() |
|
||||||
|
result = i.getSetter()
|
||||||
|
or
|
||||||
|
result =
|
||||||
|
any(Getter g |
|
||||||
|
g = i.getGetter() and
|
||||||
|
g.getAnnotatedReturnType().isRef()
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override Expr getArgument(int i) {
|
override Expr getArgument(int i) {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import Creation
|
|||||||
import Dynamic
|
import Dynamic
|
||||||
import Literal
|
import Literal
|
||||||
import LogicalOperation
|
import LogicalOperation
|
||||||
|
import Operation
|
||||||
import semmle.code.csharp.controlflow.ControlFlowElement
|
import semmle.code.csharp.controlflow.ControlFlowElement
|
||||||
import semmle.code.csharp.Location
|
import semmle.code.csharp.Location
|
||||||
import semmle.code.csharp.Stmt
|
import semmle.code.csharp.Stmt
|
||||||
@@ -211,7 +212,7 @@ class LocalConstantDeclExpr extends LocalVariableDeclExpr {
|
|||||||
* (`UnaryOperation`), a binary operation (`BinaryOperation`), or a
|
* (`UnaryOperation`), a binary operation (`BinaryOperation`), or a
|
||||||
* ternary operation (`TernaryOperation`).
|
* ternary operation (`TernaryOperation`).
|
||||||
*/
|
*/
|
||||||
class Operation extends Expr, @operation_expr {
|
class Operation extends Expr, @op_expr {
|
||||||
/** Gets the name of the operator in this operation. */
|
/** Gets the name of the operator in this operation. */
|
||||||
string getOperator() { none() }
|
string getOperator() { none() }
|
||||||
|
|
||||||
@@ -226,7 +227,7 @@ class Operation extends Expr, @operation_expr {
|
|||||||
* indirection operation (`PointerIndirectionExpr`), an address-of operation
|
* indirection operation (`PointerIndirectionExpr`), an address-of operation
|
||||||
* (`AddressOfExpr`), or a unary logical operation (`UnaryLogicalOperation`).
|
* (`AddressOfExpr`), or a unary logical operation (`UnaryLogicalOperation`).
|
||||||
*/
|
*/
|
||||||
class UnaryOperation extends Operation, @un_operation {
|
class UnaryOperation extends Operation, @un_op {
|
||||||
/** Gets the operand of this unary operation. */
|
/** Gets the operand of this unary operation. */
|
||||||
Expr getOperand() { result = this.getChild(0) }
|
Expr getOperand() { result = this.getChild(0) }
|
||||||
|
|
||||||
@@ -240,7 +241,7 @@ class UnaryOperation extends Operation, @un_operation {
|
|||||||
* a binary logical operation (`BinaryLogicalOperation`), or an
|
* a binary logical operation (`BinaryLogicalOperation`), or an
|
||||||
* assignment (`Assignment`).
|
* assignment (`Assignment`).
|
||||||
*/
|
*/
|
||||||
class BinaryOperation extends Operation, @bin_operation {
|
class BinaryOperation extends Operation, @bin_op {
|
||||||
/** Gets the left operand of this binary operation. */
|
/** Gets the left operand of this binary operation. */
|
||||||
Expr getLeftOperand() { result = this.getChild(0) }
|
Expr getLeftOperand() { result = this.getChild(0) }
|
||||||
|
|
||||||
@@ -263,7 +264,7 @@ class BinaryOperation extends Operation, @bin_operation {
|
|||||||
* A ternary operation, that is, a ternary conditional operation
|
* A ternary operation, that is, a ternary conditional operation
|
||||||
* (`ConditionalExpr`).
|
* (`ConditionalExpr`).
|
||||||
*/
|
*/
|
||||||
class TernaryOperation extends Operation, @ternary_operation { }
|
class TernaryOperation extends Operation, @ternary_op { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A parenthesized expression, for example `(2 + 3)` in
|
* A parenthesized expression, for example `(2 + 3)` in
|
||||||
|
|||||||
@@ -11,14 +11,14 @@ import Expr
|
|||||||
* a binary logical operation (`BinaryLogicalOperation`), or a ternary logical
|
* a binary logical operation (`BinaryLogicalOperation`), or a ternary logical
|
||||||
* operation (`TernaryLogicalOperation`).
|
* operation (`TernaryLogicalOperation`).
|
||||||
*/
|
*/
|
||||||
class LogicalOperation extends Operation, @log_operation {
|
class LogicalOperation extends Operation, @log_expr {
|
||||||
override string getOperator() { none() }
|
override string getOperator() { none() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A unary logical operation, that is, a logical 'not' (`LogicalNotExpr`).
|
* A unary logical operation, that is, a logical 'not' (`LogicalNotExpr`).
|
||||||
*/
|
*/
|
||||||
class UnaryLogicalOperation extends LogicalOperation, UnaryOperation, @un_log_operation { }
|
class UnaryLogicalOperation extends LogicalOperation, UnaryOperation, @un_log_op_expr { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A logical 'not', for example `!String.IsNullOrEmpty(s)`.
|
* A logical 'not', for example `!String.IsNullOrEmpty(s)`.
|
||||||
@@ -31,10 +31,10 @@ class LogicalNotExpr extends UnaryLogicalOperation, @log_not_expr {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A binary logical operation. Either a logical 'and' (`LogicalAndExpr`),
|
* A binary logical operation. Either a logical 'and' (`LogicalAndExpr`),
|
||||||
* a logical 'or' (`LogicalOrExpr`), or a null-coalescing operation
|
* a logical 'or' (`LogicalAndExpr`), or a null-coalescing operation
|
||||||
* (`NullCoalescingOperation`).
|
* (`NullCoalescingExpr`).
|
||||||
*/
|
*/
|
||||||
class BinaryLogicalOperation extends LogicalOperation, BinaryOperation, @bin_log_operation {
|
class BinaryLogicalOperation extends LogicalOperation, BinaryOperation, @bin_log_op_expr {
|
||||||
override string getOperator() { none() }
|
override string getOperator() { none() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,12 +57,7 @@ class LogicalOrExpr extends BinaryLogicalOperation, @log_or_expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A null-coalescing operation, either `x ?? y` or `x ??= y`.
|
* A null-coalescing operation, for example `s ?? ""` on line 2 in
|
||||||
*/
|
|
||||||
class NullCoalescingOperation extends BinaryLogicalOperation, @null_coalescing_operation { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A null-coalescing expression, for example `s ?? ""` on line 2 in
|
|
||||||
*
|
*
|
||||||
* ```csharp
|
* ```csharp
|
||||||
* string NonNullOrEmpty(string s) {
|
* string NonNullOrEmpty(string s) {
|
||||||
@@ -70,7 +65,9 @@ class NullCoalescingOperation extends BinaryLogicalOperation, @null_coalescing_o
|
|||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class NullCoalescingExpr extends NullCoalescingOperation, @null_coalescing_expr {
|
class NullCoalescingExpr extends BinaryLogicalOperation, NullCoalescingOperation,
|
||||||
|
@null_coalescing_expr
|
||||||
|
{
|
||||||
override string getOperator() { result = "??" }
|
override string getOperator() { result = "??" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "NullCoalescingExpr" }
|
override string getAPrimaryQlClass() { result = "NullCoalescingExpr" }
|
||||||
@@ -80,7 +77,7 @@ class NullCoalescingExpr extends NullCoalescingOperation, @null_coalescing_expr
|
|||||||
* A ternary logical operation, that is, a ternary conditional expression
|
* A ternary logical operation, that is, a ternary conditional expression
|
||||||
* (`ConditionalExpr`).
|
* (`ConditionalExpr`).
|
||||||
*/
|
*/
|
||||||
class TernaryLogicalOperation extends LogicalOperation, TernaryOperation, @ternary_log_operation { }
|
class TernaryLogicalOperation extends LogicalOperation, TernaryOperation, @ternary_log_op_expr { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A conditional expression, for example `s != null ? s.Length : -1`
|
* A conditional expression, for example `s != null ? s.Length : -1`
|
||||||
|
|||||||
@@ -1,6 +1,71 @@
|
|||||||
/**
|
/**
|
||||||
* Provides classes for operations that also have compound assignment forms.
|
* Provides classes for operations that also have compound assignment forms.
|
||||||
*/
|
*/
|
||||||
deprecated module;
|
|
||||||
|
|
||||||
import Expr
|
import Expr
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An addition operation, either `x + y` or `x += y`.
|
||||||
|
*/
|
||||||
|
class AddOperation extends BinaryOperation, @add_operation { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A subtraction operation, either `x - y` or `x -= y`.
|
||||||
|
*/
|
||||||
|
class SubOperation extends BinaryOperation, @sub_operation { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A multiplication operation, either `x * y` or `x *= y`.
|
||||||
|
*/
|
||||||
|
class MulOperation extends BinaryOperation, @mul_operation { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A division operation, either `x / y` or `x /= y`.
|
||||||
|
*/
|
||||||
|
class DivOperation extends BinaryOperation, @div_operation {
|
||||||
|
/** Gets the numerator of this division operation. */
|
||||||
|
Expr getNumerator() { result = this.getLeftOperand() }
|
||||||
|
|
||||||
|
/** Gets the denominator of this division operation. */
|
||||||
|
Expr getDenominator() { result = this.getRightOperand() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A remainder operation, either `x % y` or `x %= y`.
|
||||||
|
*/
|
||||||
|
class RemOperation extends BinaryOperation, @rem_operation { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A bitwise-and operation, either `x & y` or `x &= y`.
|
||||||
|
*/
|
||||||
|
class BitwiseAndOperation extends BinaryOperation, @and_operation { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A bitwise-or operation, either `x | y` or `x |= y`.
|
||||||
|
*/
|
||||||
|
class BitwiseOrOperation extends BinaryOperation, @or_operation { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A bitwise exclusive-or operation, either `x ^ y` or `x ^= y`.
|
||||||
|
*/
|
||||||
|
class BitwiseXorOperation extends BinaryOperation, @xor_operation { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A left-shift operation, either `x << y` or `x <<= y`.
|
||||||
|
*/
|
||||||
|
class LeftShiftOperation extends BinaryOperation, @lshift_operation { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A right-shift operation, either `x >> y` or `x >>= y`.
|
||||||
|
*/
|
||||||
|
class RightShiftOperation extends BinaryOperation, @rshift_operation { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An unsigned right-shift operation, either `x >>> y` or `x >>>= y`.
|
||||||
|
*/
|
||||||
|
class UnsignedRightShiftOperation extends BinaryOperation, @urshift_operation { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A null-coalescing operation, either `x ?? y` or `x ??= y`.
|
||||||
|
*/
|
||||||
|
class NullCoalescingOperation extends BinaryOperation, @null_coalescing_operation { }
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ private import semmle.code.csharp.frameworks.system.web.ui.WebControls
|
|||||||
private import semmle.code.csharp.frameworks.WCF
|
private import semmle.code.csharp.frameworks.WCF
|
||||||
private import semmle.code.csharp.frameworks.microsoft.Owin
|
private import semmle.code.csharp.frameworks.microsoft.Owin
|
||||||
private import semmle.code.csharp.frameworks.microsoft.AspNetCore
|
private import semmle.code.csharp.frameworks.microsoft.AspNetCore
|
||||||
private import semmle.code.csharp.frameworks.Razor
|
|
||||||
private import semmle.code.csharp.dataflow.internal.ExternalFlow
|
private import semmle.code.csharp.dataflow.internal.ExternalFlow
|
||||||
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
|
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
|
||||||
|
|
||||||
@@ -315,22 +314,6 @@ class AspNetCoreActionMethodParameter extends AspNetCoreRemoteFlowSource, DataFl
|
|||||||
override string getSourceType() { result = "ASP.NET Core MVC action method parameter" }
|
override string getSourceType() { result = "ASP.NET Core MVC action method parameter" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A parameter to a Razor Page handler method, viewed as a source of remote user input. */
|
|
||||||
class AspNetCorePageHandlerMethodParameter extends AspNetCoreRemoteFlowSource,
|
|
||||||
DataFlow::ParameterNode
|
|
||||||
{
|
|
||||||
AspNetCorePageHandlerMethodParameter() {
|
|
||||||
exists(Parameter p |
|
|
||||||
p = this.getParameter() and
|
|
||||||
p.fromSource()
|
|
||||||
|
|
|
||||||
p = any(PageModelClass pm).getAHandlerMethod().getAParameter()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override string getSourceType() { result = "ASP.NET Core Razor Page handler method parameter" }
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ExternalRemoteFlowSource extends RemoteFlowSource {
|
private class ExternalRemoteFlowSource extends RemoteFlowSource {
|
||||||
ExternalRemoteFlowSource() { sourceNode(this, "remote") }
|
ExternalRemoteFlowSource() { sourceNode(this, "remote") }
|
||||||
|
|
||||||
|
|||||||
@@ -219,7 +219,7 @@ overlayChangedFiles(
|
|||||||
/** ELEMENTS **/
|
/** ELEMENTS **/
|
||||||
|
|
||||||
@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration
|
@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration
|
||||||
| @using_directive | @type_parameter_constraints | @type_mention | @externalDataElement
|
| @using_directive | @type_parameter_constraints | @externalDataElement
|
||||||
| @xmllocatable | @asp_element | @namespace | @preprocessor_directive;
|
| @xmllocatable | @asp_element | @namespace | @preprocessor_directive;
|
||||||
|
|
||||||
@declaration = @callable | @generic | @assignable | @namespace;
|
@declaration = @callable | @generic | @assignable | @namespace;
|
||||||
@@ -1254,38 +1254,32 @@ case @expr.kind of
|
|||||||
|
|
||||||
@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr;
|
@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr;
|
||||||
|
|
||||||
@bin_arith_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr;
|
@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr;
|
||||||
@bin_arith_operation = @mul_operation | @div_operation | @rem_operation | @add_operation | @sub_operation;
|
@incr_op_expr = @pre_incr_expr | @post_incr_expr;
|
||||||
|
@decr_op_expr = @pre_decr_expr | @post_decr_expr;
|
||||||
|
@mut_op_expr = @incr_op_expr | @decr_op_expr;
|
||||||
|
@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr;
|
||||||
|
@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr;
|
||||||
|
|
||||||
@incr_operation = @pre_incr_expr | @post_incr_expr;
|
@ternary_log_op_expr = @conditional_expr;
|
||||||
@decr_operation = @pre_decr_expr | @post_decr_expr;
|
@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr;
|
||||||
@mut_operation = @incr_operation | @decr_operation;
|
@un_log_op_expr = @log_not_expr;
|
||||||
@un_arith_operation = @plus_expr | @minus_expr | @mut_operation;
|
@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr;
|
||||||
@arith_operation = @bin_arith_operation | @un_arith_operation;
|
|
||||||
|
|
||||||
@ternary_log_operation = @conditional_expr;
|
@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr
|
||||||
@bin_log_operation = @log_and_expr | @log_or_expr | @null_coalescing_operation;
|
|
||||||
@un_log_operation = @log_not_expr;
|
|
||||||
@log_operation = @un_log_operation | @bin_log_operation | @ternary_log_operation;
|
|
||||||
|
|
||||||
@bin_bit_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr
|
|
||||||
| @rshift_expr | @urshift_expr;
|
| @rshift_expr | @urshift_expr;
|
||||||
@bin_bit_operation = @and_operation | @or_operation | @xor_operation | @lshift_operation
|
@un_bit_op_expr = @bit_not_expr;
|
||||||
| @rshift_operation | @urshift_operation;
|
@bit_expr = @un_bit_op_expr | @bin_bit_op_expr;
|
||||||
@un_bit_expr = @bit_not_expr;
|
|
||||||
@un_bit_operation = @un_bit_expr;
|
|
||||||
@bit_expr = @un_bit_expr | @bin_bit_expr;
|
|
||||||
@bit_operation = @un_bit_operation | @bin_bit_operation;
|
|
||||||
|
|
||||||
@equality_op_expr = @eq_expr | @ne_expr;
|
@equality_op_expr = @eq_expr | @ne_expr;
|
||||||
@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr;
|
@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr;
|
||||||
@comp_expr = @equality_op_expr | @rel_op_expr;
|
@comp_expr = @equality_op_expr | @rel_op_expr;
|
||||||
|
|
||||||
@operation_expr = @un_operation | @bin_operation | @ternary_operation;
|
@op_expr = @un_op | @bin_op | @ternary_op;
|
||||||
|
|
||||||
@ternary_operation = @ternary_log_operation;
|
@ternary_op = @ternary_log_op_expr;
|
||||||
@bin_operation = @assign_expr | @bin_arith_operation | @bin_log_operation | @bin_bit_operation | @comp_expr;
|
@bin_op = @assign_expr | @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr;
|
||||||
@un_operation = @un_arith_operation | @un_log_operation | @un_bit_operation | @sizeof_expr
|
@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr
|
||||||
| @pointer_indirection_expr | @address_of_expr;
|
| @pointer_indirection_expr | @address_of_expr;
|
||||||
|
|
||||||
@anonymous_function_expr = @lambda_expr | @anonymous_method_expr;
|
@anonymous_function_expr = @lambda_expr | @anonymous_method_expr;
|
||||||
@@ -1369,7 +1363,7 @@ compiler_generated(unique int id: @element ref);
|
|||||||
|
|
||||||
/** CONTROL/DATA FLOW **/
|
/** CONTROL/DATA FLOW **/
|
||||||
|
|
||||||
@control_flow_element = @stmt | @expr | @parameter | @type_mention;
|
@control_flow_element = @stmt | @expr | @parameter;
|
||||||
|
|
||||||
/* XML Files */
|
/* XML Files */
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
|||||||
description: Restructure and rename types related to operations.
|
|
||||||
compatibility: full
|
|
||||||
@@ -63,7 +63,7 @@ module CallTargetStats implements StatsSig {
|
|||||||
|
|
||||||
additional predicate isNotOkCall(Call c) {
|
additional predicate isNotOkCall(Call c) {
|
||||||
not exists(c.getTarget()) and
|
not exists(c.getTarget()) and
|
||||||
not c instanceof DelegateLikeCall and
|
not c instanceof DelegateCall and
|
||||||
not c instanceof DynamicExpr and
|
not c instanceof DynamicExpr and
|
||||||
not isNoSetterPropertyCallInConstructor(c) and
|
not isNoSetterPropertyCallInConstructor(c) and
|
||||||
not isNoSetterPropertyInitialization(c) and
|
not isNoSetterPropertyInitialization(c) and
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
binarybitwise
|
binarybitwise
|
||||||
| Operators.cs:7:18:7:25 | ... >>> ... | Operators.cs:7:18:7:19 | access to local variable x1 | Operators.cs:7:25:7:25 | 2 | >>> | UnsignedRightShiftExpr |
|
| Operators.cs:7:18:7:25 | ... >>> ... | Operators.cs:7:18:7:19 | access to local variable x1 | Operators.cs:7:25:7:25 | 2 | >>> | UnsignedRightShiftExpr |
|
||||||
| Operators.cs:10:18:10:25 | ... >>> ... | Operators.cs:10:18:10:19 | access to local variable y1 | Operators.cs:10:25:10:25 | 3 | >>> | UnsignedRightShiftExpr |
|
| Operators.cs:10:18:10:25 | ... >>> ... | Operators.cs:10:18:10:19 | access to local variable y1 | Operators.cs:10:25:10:25 | 3 | >>> | UnsignedRightShiftExpr |
|
||||||
| Operators.cs:13:9:13:16 | ... >>>= ... | Operators.cs:13:9:13:9 | access to local variable z | Operators.cs:13:16:13:16 | 5 | >>>= | AssignUnsignedRightShiftExpr |
|
|
||||||
assignbitwise
|
assignbitwise
|
||||||
| Operators.cs:13:9:13:16 | ... >>>= ... | Operators.cs:13:9:13:9 | access to local variable z | Operators.cs:13:16:13:16 | 5 | >>>= | AssignUnsignedRightShiftExpr |
|
| Operators.cs:13:9:13:16 | ... >>>= ... | Operators.cs:13:9:13:9 | access to local variable z | Operators.cs:13:16:13:16 | 5 | >>>= | AssignUnsignedRightShiftExpr |
|
||||||
userdefined
|
userdefined
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ query predicate binarybitwise(
|
|||||||
}
|
}
|
||||||
|
|
||||||
query predicate assignbitwise(
|
query predicate assignbitwise(
|
||||||
AssignBitwiseExpr op, Expr left, Expr right, string name, string qlclass
|
AssignBitwiseOperation op, Expr left, Expr right, string name, string qlclass
|
||||||
) {
|
) {
|
||||||
op.getFile().getStem() = "Operators" and
|
op.getFile().getStem() = "Operators" and
|
||||||
left = op.getLeftOperand() and
|
left = op.getLeftOperand() and
|
||||||
|
|||||||
@@ -101,7 +101,6 @@ 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
|
|
||||||
# 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
|
||||||
|
|||||||
@@ -442,31 +442,4 @@ namespace My.Qltest
|
|||||||
|
|
||||||
static void Sink(object o) { }
|
static void Sink(object o) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test operator overloads
|
|
||||||
public class N
|
|
||||||
{
|
|
||||||
public void operator +=(N y) => throw null;
|
|
||||||
|
|
||||||
public void operator checked +=(N y) => throw null;
|
|
||||||
|
|
||||||
public void M1(N n)
|
|
||||||
{
|
|
||||||
var n0 = new N();
|
|
||||||
n += n0;
|
|
||||||
Sink(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void M2(N n)
|
|
||||||
{
|
|
||||||
var n0 = new N();
|
|
||||||
checked
|
|
||||||
{
|
|
||||||
n += n0;
|
|
||||||
}
|
|
||||||
Sink(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Sink(object o) { }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,16 +32,14 @@ models
|
|||||||
| 31 | Summary: My.Qltest; Library; false; GetValue; (); ; Argument[this].SyntheticField[X]; ReturnValue; value; dfc-generated |
|
| 31 | Summary: My.Qltest; Library; false; GetValue; (); ; Argument[this].SyntheticField[X]; ReturnValue; value; dfc-generated |
|
||||||
| 32 | Summary: My.Qltest; Library; false; MixedFlowArgs; (System.Object,System.Object); ; Argument[1]; ReturnValue; value; manual |
|
| 32 | Summary: My.Qltest; Library; false; MixedFlowArgs; (System.Object,System.Object); ; Argument[1]; ReturnValue; value; manual |
|
||||||
| 33 | Summary: My.Qltest; Library; false; SetValue; (System.Object); ; Argument[0]; Argument[this].SyntheticField[X]; value; dfc-generated |
|
| 33 | Summary: My.Qltest; Library; false; SetValue; (System.Object); ; Argument[0]; Argument[this].SyntheticField[X]; value; dfc-generated |
|
||||||
| 34 | Summary: My.Qltest; N; false; op_AdditionAssignment; (My.Qltest.N); ; Argument[0]; Argument[this]; taint; manual |
|
| 34 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; Method1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
||||||
| 35 | Summary: My.Qltest; N; false; op_CheckedAdditionAssignment; (My.Qltest.N); ; Argument[0]; Argument[this]; taint; manual |
|
| 35 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; StaticMethod1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
||||||
| 36 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; Method1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
| 36 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; get_Property1; (System.Object); ; Argument[0].SyntheticField[TestExtensions.Property1]; ReturnValue; value; manual |
|
||||||
| 37 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; StaticMethod1; (System.Object); ; Argument[0]; ReturnValue; value; manual |
|
| 37 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; set_Property1; (System.Object,System.Object); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.Property1]; value; manual |
|
||||||
| 38 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; get_Property1; (System.Object); ; Argument[0].SyntheticField[TestExtensions.Property1]; ReturnValue; value; manual |
|
| 38 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
||||||
| 39 | Summary: My.Qltest; TestExtensions+extension(System.Object); false; set_Property1; (System.Object,System.Object); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.Property1]; value; manual |
|
| 39 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericStaticMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
||||||
| 40 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
| 40 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; get_GenericProperty1; (T); ; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; ReturnValue; value; manual |
|
||||||
| 41 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; GenericStaticMethod1; (T); ; Argument[0]; ReturnValue; value; manual |
|
| 41 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; set_GenericProperty1; (T,T); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; value; manual |
|
||||||
| 42 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; get_GenericProperty1; (T); ; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; ReturnValue; value; manual |
|
|
||||||
| 43 | Summary: My.Qltest; TestExtensions+extension(T)<T>; false; set_GenericProperty1; (T,T); ; Argument[1]; Argument[0].SyntheticField[TestExtensions.GenericProperty1]; value; manual |
|
|
||||||
edges
|
edges
|
||||||
| ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | ExternalFlow.cs:10:29:10:32 | access to local variable arg1 : Object | provenance | |
|
| ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | ExternalFlow.cs:10:29:10:32 | access to local variable arg1 : Object | provenance | |
|
||||||
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | provenance | |
|
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | provenance | |
|
||||||
@@ -164,77 +162,69 @@ edges
|
|||||||
| ExternalFlow.cs:373:17:373:19 | access to local variable obj : Object | ExternalFlow.cs:377:45:377:47 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:373:17:373:19 | access to local variable obj : Object | ExternalFlow.cs:377:45:377:47 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:373:23:373:34 | object creation of type Object : Object | ExternalFlow.cs:373:17:373:19 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:373:23:373:34 | object creation of type Object : Object | ExternalFlow.cs:373:17:373:19 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:374:17:374:18 | access to local variable o1 : Object | ExternalFlow.cs:375:18:375:19 | access to local variable o1 | provenance | |
|
| ExternalFlow.cs:374:17:374:18 | access to local variable o1 : Object | ExternalFlow.cs:375:18:375:19 | access to local variable o1 | provenance | |
|
||||||
| ExternalFlow.cs:374:22:374:24 | access to local variable obj : Object | ExternalFlow.cs:374:22:374:34 | call to method Method1 : Object | provenance | MaD:36 |
|
| ExternalFlow.cs:374:22:374:24 | access to local variable obj : Object | ExternalFlow.cs:374:22:374:34 | call to method Method1 : Object | provenance | MaD:34 |
|
||||||
| ExternalFlow.cs:374:22:374:34 | call to method Method1 : Object | ExternalFlow.cs:374:17:374:18 | access to local variable o1 : Object | provenance | |
|
| ExternalFlow.cs:374:22:374:34 | call to method Method1 : Object | ExternalFlow.cs:374:17:374:18 | access to local variable o1 : Object | provenance | |
|
||||||
| ExternalFlow.cs:377:17:377:18 | access to local variable o2 : Object | ExternalFlow.cs:378:18:378:19 | access to local variable o2 | provenance | |
|
| ExternalFlow.cs:377:17:377:18 | access to local variable o2 : Object | ExternalFlow.cs:378:18:378:19 | access to local variable o2 | provenance | |
|
||||||
| ExternalFlow.cs:377:22:377:48 | call to method Method1 : Object | ExternalFlow.cs:377:17:377:18 | access to local variable o2 : Object | provenance | |
|
| ExternalFlow.cs:377:22:377:48 | call to method Method1 : Object | ExternalFlow.cs:377:17:377:18 | access to local variable o2 : Object | provenance | |
|
||||||
| ExternalFlow.cs:377:45:377:47 | access to local variable obj : Object | ExternalFlow.cs:377:22:377:48 | call to method Method1 : Object | provenance | MaD:36 |
|
| ExternalFlow.cs:377:45:377:47 | access to local variable obj : Object | ExternalFlow.cs:377:22:377:48 | call to method Method1 : Object | provenance | MaD:34 |
|
||||||
| ExternalFlow.cs:383:17:383:19 | access to local variable obj : Object | ExternalFlow.cs:384:43:384:45 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:383:17:383:19 | access to local variable obj : Object | ExternalFlow.cs:384:43:384:45 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:383:17:383:19 | access to local variable obj : Object | ExternalFlow.cs:387:51:387:53 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:383:17:383:19 | access to local variable obj : Object | ExternalFlow.cs:387:51:387:53 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:383:23:383:34 | object creation of type Object : Object | ExternalFlow.cs:383:17:383:19 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:383:23:383:34 | object creation of type Object : Object | ExternalFlow.cs:383:17:383:19 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:384:17:384:18 | access to local variable o1 : Object | ExternalFlow.cs:385:18:385:19 | access to local variable o1 | provenance | |
|
| ExternalFlow.cs:384:17:384:18 | access to local variable o1 : Object | ExternalFlow.cs:385:18:385:19 | access to local variable o1 | provenance | |
|
||||||
| ExternalFlow.cs:384:22:384:46 | call to method StaticMethod1 : Object | ExternalFlow.cs:384:17:384:18 | access to local variable o1 : Object | provenance | |
|
| ExternalFlow.cs:384:22:384:46 | call to method StaticMethod1 : Object | ExternalFlow.cs:384:17:384:18 | access to local variable o1 : Object | provenance | |
|
||||||
| ExternalFlow.cs:384:43:384:45 | access to local variable obj : Object | ExternalFlow.cs:384:22:384:46 | call to method StaticMethod1 : Object | provenance | MaD:37 |
|
| ExternalFlow.cs:384:43:384:45 | access to local variable obj : Object | ExternalFlow.cs:384:22:384:46 | call to method StaticMethod1 : Object | provenance | MaD:35 |
|
||||||
| ExternalFlow.cs:387:17:387:18 | access to local variable o2 : Object | ExternalFlow.cs:388:18:388:19 | access to local variable o2 | provenance | |
|
| ExternalFlow.cs:387:17:387:18 | access to local variable o2 : Object | ExternalFlow.cs:388:18:388:19 | access to local variable o2 | provenance | |
|
||||||
| ExternalFlow.cs:387:22:387:54 | call to method StaticMethod1 : Object | ExternalFlow.cs:387:17:387:18 | access to local variable o2 : Object | provenance | |
|
| ExternalFlow.cs:387:22:387:54 | call to method StaticMethod1 : Object | ExternalFlow.cs:387:17:387:18 | access to local variable o2 : Object | provenance | |
|
||||||
| ExternalFlow.cs:387:51:387:53 | access to local variable obj : Object | ExternalFlow.cs:387:22:387:54 | call to method StaticMethod1 : Object | provenance | MaD:37 |
|
| ExternalFlow.cs:387:51:387:53 | access to local variable obj : Object | ExternalFlow.cs:387:22:387:54 | call to method StaticMethod1 : Object | provenance | MaD:35 |
|
||||||
| ExternalFlow.cs:393:17:393:19 | access to local variable obj : Object | ExternalFlow.cs:394:27:394:29 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:393:17:393:19 | access to local variable obj : Object | ExternalFlow.cs:394:27:394:29 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:393:23:393:34 | object creation of type Object : Object | ExternalFlow.cs:393:17:393:19 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:393:23:393:34 | object creation of type Object : Object | ExternalFlow.cs:393:17:393:19 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:394:13:394:13 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:395:22:395:22 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | |
|
| ExternalFlow.cs:394:13:394:13 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:395:22:395:22 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | |
|
||||||
| ExternalFlow.cs:394:27:394:29 | access to local variable obj : Object | ExternalFlow.cs:394:13:394:13 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:39 |
|
| ExternalFlow.cs:394:27:394:29 | access to local variable obj : Object | ExternalFlow.cs:394:13:394:13 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:37 |
|
||||||
| ExternalFlow.cs:395:17:395:18 | access to local variable o1 : Object | ExternalFlow.cs:396:18:396:19 | access to local variable o1 | provenance | |
|
| ExternalFlow.cs:395:17:395:18 | access to local variable o1 : Object | ExternalFlow.cs:396:18:396:19 | access to local variable o1 | provenance | |
|
||||||
| ExternalFlow.cs:395:22:395:22 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:395:22:395:32 | access to property Property1 : Object | provenance | MaD:38 |
|
| ExternalFlow.cs:395:22:395:22 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:395:22:395:32 | access to property Property1 : Object | provenance | MaD:36 |
|
||||||
| ExternalFlow.cs:395:22:395:32 | access to property Property1 : Object | ExternalFlow.cs:395:17:395:18 | access to local variable o1 : Object | provenance | |
|
| ExternalFlow.cs:395:22:395:32 | access to property Property1 : Object | ExternalFlow.cs:395:17:395:18 | access to local variable o1 : Object | provenance | |
|
||||||
| ExternalFlow.cs:401:17:401:19 | access to local variable obj : Object | ExternalFlow.cs:402:45:402:47 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:401:17:401:19 | access to local variable obj : Object | ExternalFlow.cs:402:45:402:47 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:401:23:401:34 | object creation of type Object : Object | ExternalFlow.cs:401:17:401:19 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:401:23:401:34 | object creation of type Object : Object | ExternalFlow.cs:401:17:401:19 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:402:42:402:42 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:403:51:403:51 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | |
|
| ExternalFlow.cs:402:42:402:42 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:403:51:403:51 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | |
|
||||||
| ExternalFlow.cs:402:45:402:47 | access to local variable obj : Object | ExternalFlow.cs:402:42:402:42 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:39 |
|
| ExternalFlow.cs:402:45:402:47 | access to local variable obj : Object | ExternalFlow.cs:402:42:402:42 | [post] access to parameter o : Object [synthetic TestExtensions.Property1] : Object | provenance | MaD:37 |
|
||||||
| ExternalFlow.cs:403:17:403:18 | access to local variable o1 : Object | ExternalFlow.cs:404:18:404:19 | access to local variable o1 | provenance | |
|
| ExternalFlow.cs:403:17:403:18 | access to local variable o1 : Object | ExternalFlow.cs:404:18:404:19 | access to local variable o1 | provenance | |
|
||||||
| ExternalFlow.cs:403:22:403:52 | call to extension accessor get_Property1 : Object | ExternalFlow.cs:403:17:403:18 | access to local variable o1 : Object | provenance | |
|
| ExternalFlow.cs:403:22:403:52 | call to extension accessor get_Property1 : Object | ExternalFlow.cs:403:17:403:18 | access to local variable o1 : Object | provenance | |
|
||||||
| ExternalFlow.cs:403:51:403:51 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:403:22:403:52 | call to extension accessor get_Property1 : Object | provenance | MaD:38 |
|
| ExternalFlow.cs:403:51:403:51 | access to parameter o : Object [synthetic TestExtensions.Property1] : Object | ExternalFlow.cs:403:22:403:52 | call to extension accessor get_Property1 : Object | provenance | MaD:36 |
|
||||||
| ExternalFlow.cs:409:17:409:19 | access to local variable obj : Object | ExternalFlow.cs:410:22:410:24 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:409:17:409:19 | access to local variable obj : Object | ExternalFlow.cs:410:22:410:24 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:409:17:409:19 | access to local variable obj : Object | ExternalFlow.cs:413:52:413:54 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:409:17:409:19 | access to local variable obj : Object | ExternalFlow.cs:413:52:413:54 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:409:23:409:34 | object creation of type Object : Object | ExternalFlow.cs:409:17:409:19 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:409:23:409:34 | object creation of type Object : Object | ExternalFlow.cs:409:17:409:19 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:410:17:410:18 | access to local variable o1 : Object | ExternalFlow.cs:411:18:411:19 | access to local variable o1 | provenance | |
|
| ExternalFlow.cs:410:17:410:18 | access to local variable o1 : Object | ExternalFlow.cs:411:18:411:19 | access to local variable o1 | provenance | |
|
||||||
| ExternalFlow.cs:410:22:410:24 | access to local variable obj : Object | ExternalFlow.cs:410:22:410:41 | call to method GenericMethod1 : Object | provenance | MaD:40 |
|
| ExternalFlow.cs:410:22:410:24 | access to local variable obj : Object | ExternalFlow.cs:410:22:410:41 | call to method GenericMethod1 : Object | provenance | MaD:38 |
|
||||||
| ExternalFlow.cs:410:22:410:41 | call to method GenericMethod1 : Object | ExternalFlow.cs:410:17:410:18 | access to local variable o1 : Object | provenance | |
|
| ExternalFlow.cs:410:22:410:41 | call to method GenericMethod1 : Object | ExternalFlow.cs:410:17:410:18 | access to local variable o1 : Object | provenance | |
|
||||||
| ExternalFlow.cs:413:17:413:18 | access to local variable o2 : Object | ExternalFlow.cs:414:18:414:19 | access to local variable o2 | provenance | |
|
| ExternalFlow.cs:413:17:413:18 | access to local variable o2 : Object | ExternalFlow.cs:414:18:414:19 | access to local variable o2 | provenance | |
|
||||||
| ExternalFlow.cs:413:22:413:55 | call to method GenericMethod1 : Object | ExternalFlow.cs:413:17:413:18 | access to local variable o2 : Object | provenance | |
|
| ExternalFlow.cs:413:22:413:55 | call to method GenericMethod1 : Object | ExternalFlow.cs:413:17:413:18 | access to local variable o2 : Object | provenance | |
|
||||||
| ExternalFlow.cs:413:52:413:54 | access to local variable obj : Object | ExternalFlow.cs:413:22:413:55 | call to method GenericMethod1 : Object | provenance | MaD:40 |
|
| ExternalFlow.cs:413:52:413:54 | access to local variable obj : Object | ExternalFlow.cs:413:22:413:55 | call to method GenericMethod1 : Object | provenance | MaD:38 |
|
||||||
| ExternalFlow.cs:419:17:419:19 | access to local variable obj : Object | ExternalFlow.cs:420:50:420:52 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:419:17:419:19 | access to local variable obj : Object | ExternalFlow.cs:420:50:420:52 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:419:17:419:19 | access to local variable obj : Object | ExternalFlow.cs:423:58:423:60 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:419:17:419:19 | access to local variable obj : Object | ExternalFlow.cs:423:58:423:60 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:419:23:419:34 | object creation of type Object : Object | ExternalFlow.cs:419:17:419:19 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:419:23:419:34 | object creation of type Object : Object | ExternalFlow.cs:419:17:419:19 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:420:17:420:18 | access to local variable o1 : Object | ExternalFlow.cs:421:18:421:19 | access to local variable o1 | provenance | |
|
| ExternalFlow.cs:420:17:420:18 | access to local variable o1 : Object | ExternalFlow.cs:421:18:421:19 | access to local variable o1 | provenance | |
|
||||||
| ExternalFlow.cs:420:22:420:53 | call to method GenericStaticMethod1 : Object | ExternalFlow.cs:420:17:420:18 | access to local variable o1 : Object | provenance | |
|
| ExternalFlow.cs:420:22:420:53 | call to method GenericStaticMethod1 : Object | ExternalFlow.cs:420:17:420:18 | access to local variable o1 : Object | provenance | |
|
||||||
| ExternalFlow.cs:420:50:420:52 | access to local variable obj : Object | ExternalFlow.cs:420:22:420:53 | call to method GenericStaticMethod1 : Object | provenance | MaD:41 |
|
| ExternalFlow.cs:420:50:420:52 | access to local variable obj : Object | ExternalFlow.cs:420:22:420:53 | call to method GenericStaticMethod1 : Object | provenance | MaD:39 |
|
||||||
| ExternalFlow.cs:423:17:423:18 | access to local variable o2 : Object | ExternalFlow.cs:424:18:424:19 | access to local variable o2 | provenance | |
|
| ExternalFlow.cs:423:17:423:18 | access to local variable o2 : Object | ExternalFlow.cs:424:18:424:19 | access to local variable o2 | provenance | |
|
||||||
| ExternalFlow.cs:423:22:423:61 | call to method GenericStaticMethod1 : Object | ExternalFlow.cs:423:17:423:18 | access to local variable o2 : Object | provenance | |
|
| ExternalFlow.cs:423:22:423:61 | call to method GenericStaticMethod1 : Object | ExternalFlow.cs:423:17:423:18 | access to local variable o2 : Object | provenance | |
|
||||||
| ExternalFlow.cs:423:58:423:60 | access to local variable obj : Object | ExternalFlow.cs:423:22:423:61 | call to method GenericStaticMethod1 : Object | provenance | MaD:41 |
|
| ExternalFlow.cs:423:58:423:60 | access to local variable obj : Object | ExternalFlow.cs:423:22:423:61 | call to method GenericStaticMethod1 : Object | provenance | MaD:39 |
|
||||||
| ExternalFlow.cs:429:17:429:19 | access to local variable obj : Object | ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:429:17:429:19 | access to local variable obj : Object | ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:429:23:429:34 | object creation of type Object : Object | ExternalFlow.cs:429:17:429:19 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:429:23:429:34 | object creation of type Object : Object | ExternalFlow.cs:429:17:429:19 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [property GenericProperty1] : Object | ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [property GenericProperty1] : Object | provenance | |
|
| ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [property GenericProperty1] : Object | ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [property GenericProperty1] : Object | provenance | |
|
||||||
| ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | |
|
| ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | |
|
||||||
| ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [property GenericProperty1] : Object | provenance | |
|
| ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [property GenericProperty1] : Object | provenance | |
|
||||||
| ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:43 |
|
| ExternalFlow.cs:430:34:430:36 | access to local variable obj : Object | ExternalFlow.cs:430:13:430:13 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:41 |
|
||||||
| ExternalFlow.cs:431:17:431:18 | access to local variable o1 : Object | ExternalFlow.cs:432:18:432:19 | access to local variable o1 | provenance | |
|
| ExternalFlow.cs:431:17:431:18 | access to local variable o1 : Object | ExternalFlow.cs:432:18:432:19 | access to local variable o1 | provenance | |
|
||||||
| ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [property GenericProperty1] : Object | ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | provenance | |
|
| ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [property GenericProperty1] : Object | ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | provenance | |
|
||||||
| ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | provenance | MaD:42 |
|
| ExternalFlow.cs:431:22:431:22 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | provenance | MaD:40 |
|
||||||
| ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | ExternalFlow.cs:431:17:431:18 | access to local variable o1 : Object | provenance | |
|
| ExternalFlow.cs:431:22:431:39 | access to property GenericProperty1 : Object | ExternalFlow.cs:431:17:431:18 | access to local variable o1 : Object | provenance | |
|
||||||
| ExternalFlow.cs:437:17:437:19 | access to local variable obj : Object | ExternalFlow.cs:438:52:438:54 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:437:17:437:19 | access to local variable obj : Object | ExternalFlow.cs:438:52:438:54 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:437:23:437:34 | object creation of type Object : Object | ExternalFlow.cs:437:17:437:19 | access to local variable obj : Object | provenance | |
|
| ExternalFlow.cs:437:23:437:34 | object creation of type Object : Object | ExternalFlow.cs:437:17:437:19 | access to local variable obj : Object | provenance | |
|
||||||
| ExternalFlow.cs:438:49:438:49 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | |
|
| ExternalFlow.cs:438:49:438:49 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | |
|
||||||
| ExternalFlow.cs:438:52:438:54 | access to local variable obj : Object | ExternalFlow.cs:438:49:438:49 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:43 |
|
| ExternalFlow.cs:438:52:438:54 | access to local variable obj : Object | ExternalFlow.cs:438:49:438:49 | [post] access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | provenance | MaD:41 |
|
||||||
| ExternalFlow.cs:439:17:439:18 | access to local variable o1 : Object | ExternalFlow.cs:440:18:440:19 | access to local variable o1 | provenance | |
|
| ExternalFlow.cs:439:17:439:18 | access to local variable o1 : Object | ExternalFlow.cs:440:18:440:19 | access to local variable o1 | provenance | |
|
||||||
| ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | ExternalFlow.cs:439:17:439:18 | access to local variable o1 : Object | provenance | |
|
| ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | ExternalFlow.cs:439:17:439:18 | access to local variable o1 : Object | provenance | |
|
||||||
| ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | provenance | MaD:42 |
|
| ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | provenance | MaD:40 |
|
||||||
| ExternalFlow.cs:455:17:455:18 | access to local variable n0 : N | ExternalFlow.cs:456:18:456:19 | access to local variable n0 : N | provenance | |
|
|
||||||
| ExternalFlow.cs:455:22:455:28 | object creation of type N : N | ExternalFlow.cs:455:17:455:18 | access to local variable n0 : N | provenance | |
|
|
||||||
| ExternalFlow.cs:456:13:456:13 | [post] access to parameter n : N | ExternalFlow.cs:457:18:457:18 | access to parameter n | provenance | |
|
|
||||||
| ExternalFlow.cs:456:18:456:19 | access to local variable n0 : N | ExternalFlow.cs:456:13:456:13 | [post] access to parameter n : N | provenance | MaD:34 |
|
|
||||||
| ExternalFlow.cs:462:17:462:18 | access to local variable n0 : N | ExternalFlow.cs:465:22:465:23 | access to local variable n0 : N | provenance | |
|
|
||||||
| ExternalFlow.cs:462:22:462:28 | object creation of type N : N | ExternalFlow.cs:462:17:462:18 | access to local variable n0 : N | provenance | |
|
|
||||||
| ExternalFlow.cs:465:17:465:17 | [post] access to parameter n : N | ExternalFlow.cs:467:18:467:18 | access to parameter n | provenance | |
|
|
||||||
| ExternalFlow.cs:465:22:465:23 | access to local variable n0 : N | ExternalFlow.cs:465:17:465:17 | [post] access to parameter n : N | provenance | MaD:35 |
|
|
||||||
nodes
|
nodes
|
||||||
| ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | semmle.label | access to local variable arg1 : Object |
|
| ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | semmle.label | access to local variable arg1 : Object |
|
||||||
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
|
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
|
||||||
@@ -453,16 +443,6 @@ nodes
|
|||||||
| ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | semmle.label | call to extension accessor get_GenericProperty1 : Object |
|
| ExternalFlow.cs:439:22:439:59 | call to extension accessor get_GenericProperty1 : Object | semmle.label | call to extension accessor get_GenericProperty1 : Object |
|
||||||
| ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | semmle.label | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object |
|
| ExternalFlow.cs:439:58:439:58 | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object | semmle.label | access to parameter o : Object [synthetic TestExtensions.GenericProperty1] : Object |
|
||||||
| ExternalFlow.cs:440:18:440:19 | access to local variable o1 | semmle.label | access to local variable o1 |
|
| ExternalFlow.cs:440:18:440:19 | access to local variable o1 | semmle.label | access to local variable o1 |
|
||||||
| ExternalFlow.cs:455:17:455:18 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
|
||||||
| ExternalFlow.cs:455:22:455:28 | object creation of type N : N | semmle.label | object creation of type N : N |
|
|
||||||
| ExternalFlow.cs:456:13:456:13 | [post] access to parameter n : N | semmle.label | [post] access to parameter n : N |
|
|
||||||
| ExternalFlow.cs:456:18:456:19 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
|
||||||
| ExternalFlow.cs:457:18:457:18 | access to parameter n | semmle.label | access to parameter n |
|
|
||||||
| ExternalFlow.cs:462:17:462:18 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
|
||||||
| ExternalFlow.cs:462:22:462:28 | object creation of type N : N | semmle.label | object creation of type N : N |
|
|
||||||
| ExternalFlow.cs:465:17:465:17 | [post] access to parameter n : N | semmle.label | [post] access to parameter n : N |
|
|
||||||
| ExternalFlow.cs:465:22:465:23 | access to local variable n0 : N | semmle.label | access to local variable n0 : N |
|
|
||||||
| ExternalFlow.cs:467:18:467:18 | access to parameter n | semmle.label | access to parameter n |
|
|
||||||
subpaths
|
subpaths
|
||||||
| ExternalFlow.cs:84:29:84:32 | access to local variable objs : null [element] : Object | ExternalFlow.cs:84:35:84:35 | o : Object | ExternalFlow.cs:84:40:84:40 | access to parameter o : Object | ExternalFlow.cs:84:25:84:41 | call to method Map<Object,Object> : T[] [element] : Object |
|
| ExternalFlow.cs:84:29:84:32 | access to local variable objs : null [element] : Object | ExternalFlow.cs:84:35:84:35 | o : Object | ExternalFlow.cs:84:40:84:40 | access to parameter o : Object | ExternalFlow.cs:84:25:84:41 | call to method Map<Object,Object> : T[] [element] : Object |
|
||||||
invalidModelRow
|
invalidModelRow
|
||||||
@@ -509,5 +489,3 @@ invalidModelRow
|
|||||||
| ExternalFlow.cs:424:18:424:19 | access to local variable o2 | ExternalFlow.cs:419:23:419:34 | object creation of type Object : Object | ExternalFlow.cs:424:18:424:19 | access to local variable o2 | $@ | ExternalFlow.cs:419:23:419:34 | object creation of type Object : Object | object creation of type Object : Object |
|
| ExternalFlow.cs:424:18:424:19 | access to local variable o2 | ExternalFlow.cs:419:23:419:34 | object creation of type Object : Object | ExternalFlow.cs:424:18:424:19 | access to local variable o2 | $@ | ExternalFlow.cs:419:23:419:34 | object creation of type Object : Object | object creation of type Object : Object |
|
||||||
| ExternalFlow.cs:432:18:432:19 | access to local variable o1 | ExternalFlow.cs:429:23:429:34 | object creation of type Object : Object | ExternalFlow.cs:432:18:432:19 | access to local variable o1 | $@ | ExternalFlow.cs:429:23:429:34 | object creation of type Object : Object | object creation of type Object : Object |
|
| ExternalFlow.cs:432:18:432:19 | access to local variable o1 | ExternalFlow.cs:429:23:429:34 | object creation of type Object : Object | ExternalFlow.cs:432:18:432:19 | access to local variable o1 | $@ | ExternalFlow.cs:429:23:429:34 | object creation of type Object : Object | object creation of type Object : Object |
|
||||||
| ExternalFlow.cs:440:18:440:19 | access to local variable o1 | ExternalFlow.cs:437:23:437:34 | object creation of type Object : Object | ExternalFlow.cs:440:18:440:19 | access to local variable o1 | $@ | ExternalFlow.cs:437:23:437:34 | object creation of type Object : Object | object creation of type Object : Object |
|
| ExternalFlow.cs:440:18:440:19 | access to local variable o1 | ExternalFlow.cs:437:23:437:34 | object creation of type Object : Object | ExternalFlow.cs:440:18:440:19 | access to local variable o1 | $@ | ExternalFlow.cs:437:23:437:34 | object creation of type Object : Object | object creation of type Object : Object |
|
||||||
| ExternalFlow.cs:457:18:457:18 | access to parameter n | ExternalFlow.cs:455:22:455:28 | object creation of type N : N | ExternalFlow.cs:457:18:457:18 | access to parameter n | $@ | ExternalFlow.cs:455:22:455:28 | object creation of type N : N | object creation of type N : N |
|
|
||||||
| ExternalFlow.cs:467:18:467:18 | access to parameter n | ExternalFlow.cs:462:22:462:28 | object creation of type N : N | ExternalFlow.cs:467:18:467:18 | access to parameter n | $@ | ExternalFlow.cs:462:22:462:28 | object creation of type N : N | object creation of type N : N |
|
|
||||||
|
|||||||
@@ -53,8 +53,6 @@ extensions:
|
|||||||
- ["My.Qltest", "TestExtensions+extension(T)<T>", false, "GenericStaticMethod1", "(T)", "", "Argument[0]", "ReturnValue", "value", "manual"]
|
- ["My.Qltest", "TestExtensions+extension(T)<T>", false, "GenericStaticMethod1", "(T)", "", "Argument[0]", "ReturnValue", "value", "manual"]
|
||||||
- ["My.Qltest", "TestExtensions+extension(T)<T>", false, "get_GenericProperty1", "(T)", "", "Argument[0].SyntheticField[TestExtensions.GenericProperty1]", "ReturnValue", "value", "manual"]
|
- ["My.Qltest", "TestExtensions+extension(T)<T>", false, "get_GenericProperty1", "(T)", "", "Argument[0].SyntheticField[TestExtensions.GenericProperty1]", "ReturnValue", "value", "manual"]
|
||||||
- ["My.Qltest", "TestExtensions+extension(T)<T>", false, "set_GenericProperty1", "(T,T)", "", "Argument[1]", "Argument[0].SyntheticField[TestExtensions.GenericProperty1]", "value", "manual"]
|
- ["My.Qltest", "TestExtensions+extension(T)<T>", false, "set_GenericProperty1", "(T,T)", "", "Argument[1]", "Argument[0].SyntheticField[TestExtensions.GenericProperty1]", "value", "manual"]
|
||||||
- ["My.Qltest", "N", false, "op_AdditionAssignment", "(My.Qltest.N)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
|
||||||
- ["My.Qltest", "N", false, "op_CheckedAdditionAssignment", "(My.Qltest.N)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
|
||||||
|
|
||||||
- addsTo:
|
- addsTo:
|
||||||
pack: codeql/csharp-all
|
pack: codeql/csharp-all
|
||||||
|
|||||||
@@ -63,32 +63,4 @@ namespace Testing
|
|||||||
{
|
{
|
||||||
public void MyActionMethod(string param) { }
|
public void MyActionMethod(string param) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Razor Page handler tests
|
|
||||||
public class MyPageModel : Microsoft.AspNetCore.Mvc.RazorPages.PageModel
|
|
||||||
{
|
|
||||||
// Handler method parameters are remote flow sources
|
|
||||||
public void OnGet(string id) { }
|
|
||||||
|
|
||||||
public void OnPost(string command, int count) { }
|
|
||||||
|
|
||||||
public void OnPostAsync(string data) { }
|
|
||||||
|
|
||||||
public void OnPut(string value) { }
|
|
||||||
|
|
||||||
public void OnDelete(string itemId) { }
|
|
||||||
|
|
||||||
// Not a handler method — does not start with "On", so not a flow source
|
|
||||||
public void GetUser(string userId) { }
|
|
||||||
|
|
||||||
// Excluded by [NonHandler] attribute, so not a flow source
|
|
||||||
[Microsoft.AspNetCore.Mvc.RazorPages.NonHandlerAttribute]
|
|
||||||
public void OnGetNonHandler(string param) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subclass of a PageModel subclass
|
|
||||||
public class DerivedPageModel : MyPageModel
|
|
||||||
{
|
|
||||||
public void OnPost(string derivedParam) { }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,3 @@ remoteFlowSources
|
|||||||
| AspRemoteFlowSource.cs:54:69:54:82 | mapDeleteParam |
|
| AspRemoteFlowSource.cs:54:69:54:82 | mapDeleteParam |
|
||||||
| AspRemoteFlowSource.cs:56:41:56:44 | item |
|
| AspRemoteFlowSource.cs:56:41:56:44 | item |
|
||||||
| AspRemoteFlowSource.cs:64:43:64:47 | param |
|
| AspRemoteFlowSource.cs:64:43:64:47 | param |
|
||||||
| AspRemoteFlowSource.cs:71:34:71:35 | id |
|
|
||||||
| AspRemoteFlowSource.cs:73:35:73:41 | command |
|
|
||||||
| AspRemoteFlowSource.cs:73:48:73:52 | count |
|
|
||||||
| AspRemoteFlowSource.cs:75:40:75:43 | data |
|
|
||||||
| AspRemoteFlowSource.cs:77:34:77:38 | value |
|
|
||||||
| AspRemoteFlowSource.cs:79:37:79:42 | itemId |
|
|
||||||
| AspRemoteFlowSource.cs:92:35:92:46 | derivedParam |
|
|
||||||
|
|||||||
@@ -293,69 +293,3 @@ properties.cs:
|
|||||||
# 160| 0: [LocalVariableAccess] access to local variable x
|
# 160| 0: [LocalVariableAccess] access to local variable x
|
||||||
# 160| 1: [PropertyCall] access to property Prop
|
# 160| 1: [PropertyCall] access to property Prop
|
||||||
# 160| -1: [LocalVariableAccess] access to local variable s
|
# 160| -1: [LocalVariableAccess] access to local variable s
|
||||||
# 164| 13: [Class] BaseClass
|
|
||||||
# 166| 6: [Property] Value
|
|
||||||
# 166| -1: [TypeMention] int
|
|
||||||
# 168| 3: [Getter] get_Value
|
|
||||||
# 168| 4: [BlockStmt] {...}
|
|
||||||
# 168| 0: [ReturnStmt] return ...;
|
|
||||||
# 168| 0: [FieldAccess] access to field Value.field
|
|
||||||
# 169| 4: [Setter] set_Value
|
|
||||||
#-----| 2: (Parameters)
|
|
||||||
# 169| 0: [Parameter] value
|
|
||||||
# 169| 4: [BlockStmt] {...}
|
|
||||||
# 169| 0: [ExprStmt] ...;
|
|
||||||
# 169| 0: [AssignExpr] ... = ...
|
|
||||||
# 169| 0: [FieldAccess] access to field Value.field
|
|
||||||
# 169| 1: [ParameterAccess] access to parameter value
|
|
||||||
# 166| 7: [Field] Value.field
|
|
||||||
# 173| 14: [Class] DerivedClass1
|
|
||||||
#-----| 3: (Base types)
|
|
||||||
# 173| 0: [TypeMention] BaseClass
|
|
||||||
# 175| 6: [Property] Value
|
|
||||||
# 175| -1: [TypeMention] int
|
|
||||||
# 177| 3: [Getter] get_Value
|
|
||||||
# 177| 4: [BlockStmt] {...}
|
|
||||||
# 177| 0: [ReturnStmt] return ...;
|
|
||||||
# 177| 0: [IntLiteral] 20
|
|
||||||
# 181| 15: [Class] DerivedClass2
|
|
||||||
#-----| 3: (Base types)
|
|
||||||
# 181| 0: [TypeMention] BaseClass
|
|
||||||
# 183| 16: [Class] TestPartialPropertyOverride
|
|
||||||
# 185| 6: [Method] M
|
|
||||||
# 185| -1: [TypeMention] Void
|
|
||||||
# 186| 4: [BlockStmt] {...}
|
|
||||||
# 187| 0: [LocalVariableDeclStmt] ... ...;
|
|
||||||
# 187| 0: [LocalVariableDeclAndInitExpr] DerivedClass1 d1 = ...
|
|
||||||
# 187| -1: [TypeMention] DerivedClass1
|
|
||||||
# 187| 0: [LocalVariableAccess] access to local variable d1
|
|
||||||
# 187| 1: [ObjectCreation] object creation of type DerivedClass1
|
|
||||||
# 187| 0: [TypeMention] DerivedClass1
|
|
||||||
# 188| 1: [ExprStmt] ...;
|
|
||||||
# 188| 0: [AssignExpr] ... = ...
|
|
||||||
# 188| 0: [PropertyCall] access to property Value
|
|
||||||
# 188| -1: [LocalVariableAccess] access to local variable d1
|
|
||||||
# 188| 1: [IntLiteral] 11
|
|
||||||
# 189| 2: [LocalVariableDeclStmt] ... ...;
|
|
||||||
# 189| 0: [LocalVariableDeclAndInitExpr] Int32 test1 = ...
|
|
||||||
# 189| -1: [TypeMention] int
|
|
||||||
# 189| 0: [LocalVariableAccess] access to local variable test1
|
|
||||||
# 189| 1: [PropertyCall] access to property Value
|
|
||||||
# 189| -1: [LocalVariableAccess] access to local variable d1
|
|
||||||
# 191| 3: [LocalVariableDeclStmt] ... ...;
|
|
||||||
# 191| 0: [LocalVariableDeclAndInitExpr] DerivedClass2 d2 = ...
|
|
||||||
# 191| -1: [TypeMention] DerivedClass2
|
|
||||||
# 191| 0: [LocalVariableAccess] access to local variable d2
|
|
||||||
# 191| 1: [ObjectCreation] object creation of type DerivedClass2
|
|
||||||
# 191| 0: [TypeMention] DerivedClass2
|
|
||||||
# 192| 4: [ExprStmt] ...;
|
|
||||||
# 192| 0: [AssignExpr] ... = ...
|
|
||||||
# 192| 0: [PropertyCall] access to property Value
|
|
||||||
# 192| -1: [LocalVariableAccess] access to local variable d2
|
|
||||||
# 192| 1: [IntLiteral] 12
|
|
||||||
# 193| 5: [LocalVariableDeclStmt] ... ...;
|
|
||||||
# 193| 0: [LocalVariableDeclAndInitExpr] Int32 test2 = ...
|
|
||||||
# 193| -1: [TypeMention] int
|
|
||||||
# 193| 0: [LocalVariableAccess] access to local variable test2
|
|
||||||
# 193| 1: [PropertyCall] access to property Value
|
|
||||||
# 193| -1: [LocalVariableAccess] access to local variable d2
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
| Prop.field |
|
| Prop.field |
|
||||||
| Value.field |
|
|
||||||
| caption |
|
| caption |
|
||||||
| next |
|
| next |
|
||||||
| x |
|
| x |
|
||||||
|
|||||||
@@ -6,7 +6,3 @@
|
|||||||
| properties.cs:71:28:71:28 | Y | properties.cs:83:39:83:44 | access to property Y | properties.cs:74:13:74:15 | set_Y |
|
| properties.cs:71:28:71:28 | Y | properties.cs:83:39:83:44 | access to property Y | properties.cs:74:13:74:15 | set_Y |
|
||||||
| properties.cs:146:24:146:27 | Prop | properties.cs:159:13:159:18 | access to property Prop | properties.cs:148:13:148:15 | get_Prop |
|
| properties.cs:146:24:146:27 | Prop | properties.cs:159:13:159:18 | access to property Prop | properties.cs:148:13:148:15 | get_Prop |
|
||||||
| properties.cs:146:24:146:27 | Prop | properties.cs:160:21:160:26 | access to property Prop | properties.cs:148:13:148:15 | get_Prop |
|
| properties.cs:146:24:146:27 | Prop | properties.cs:160:21:160:26 | access to property Prop | properties.cs:148:13:148:15 | get_Prop |
|
||||||
| properties.cs:166:28:166:32 | Value | properties.cs:192:13:192:20 | access to property Value | properties.cs:169:13:169:15 | set_Value |
|
|
||||||
| properties.cs:166:28:166:32 | Value | properties.cs:193:25:193:32 | access to property Value | properties.cs:168:13:168:15 | get_Value |
|
|
||||||
| properties.cs:175:29:175:33 | Value | properties.cs:188:13:188:20 | access to property Value | properties.cs:169:13:169:15 | set_Value |
|
|
||||||
| properties.cs:175:29:175:33 | Value | properties.cs:189:25:189:32 | access to property Value | properties.cs:177:13:177:15 | get_Value |
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user