diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8ddae33fd7b..b86009ef6da 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -5,8 +5,6 @@ on: branches: - main - 'rc/*' - paths: - - 'csharp/**' pull_request: branches: - main diff --git a/.github/workflows/docs-review.yml b/.github/workflows/docs-review.yml new file mode 100644 index 00000000000..8b5f396fa9f --- /dev/null +++ b/.github/workflows/docs-review.yml @@ -0,0 +1,29 @@ +# When a PR is labelled with 'ready-for-docs-review', +# this workflow comments on the PR to notify the GitHub CodeQL docs team. +name: Request docs review +on: + # Runs in the context of the base repo. + # This gives the workflow write access to comment on PRs. + # The workflow should not check out or build the given ref, + # or use untrusted data from the event payload in a command line. + pull_request_target: + types: [labeled] + +jobs: + request-docs-review: + name: Request docs review + # Run only on labelled PRs to the main repository. + # Do not run on PRs to forks. + if: + github.event.label.name == 'ready-for-docs-review' + && github.event.pull_request.draft == false + && github.event.pull_request.base.repo.full_name == 'github/codeql' + runs-on: ubuntu-latest + steps: + - name: Comment to request docs review + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + gh pr comment "$PR_NUMBER" --repo "github/codeql" \ + --body "Hello @github/docs-content-codeql: this PR is ready for docs review." diff --git a/CODEOWNERS b/CODEOWNERS index 9d0596fbc96..da670301f30 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -10,3 +10,10 @@ /java/**/experimental/**/* @github/codeql-java @xcorail /javascript/**/experimental/**/* @github/codeql-javascript @xcorail /python/**/experimental/**/* @github/codeql-python @xcorail + +# Notify members of codeql-go about PRs to the shared data-flow library files +/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @github/codeql-java @github/codeql-go +/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @github/codeql-java @github/codeql-go +/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @github/codeql-java @github/codeql-go +/java/ql/src/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll @github/codeql-java @github/codeql-go +/java/ql/src/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll @github/codeql-java @github/codeql-go diff --git a/config/identical-files.json b/config/identical-files.json index c6f4eb1dbde..b63690c5f1e 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -425,5 +425,14 @@ "java/ql/src/IDEContextual.qll", "javascript/ql/src/IDEContextual.qll", "python/ql/src/analysis/IDEContextual.qll" + ], + "SSA C#": [ + "csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll", + "csharp/ql/src/semmle/code/csharp/controlflow/internal/pressa/SsaImplCommon.qll", + "csharp/ql/src/semmle/code/csharp/dataflow/internal/basessa/SsaImplCommon.qll" + ], + "CryptoAlgorithms Python/JS": [ + "javascript/ql/src/semmle/javascript/security/CryptoAlgorithms.qll", + "python/ql/src/semmle/crypto/Crypto.qll" ] } diff --git a/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/Semmle.Autobuild.Cpp.Tests.csproj b/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/Semmle.Autobuild.Cpp.Tests.csproj index 7de677b5610..9bf293c7e8d 100644 --- a/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/Semmle.Autobuild.Cpp.Tests.csproj +++ b/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/Semmle.Autobuild.Cpp.Tests.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 false win-x64;linux-x64;osx-x64 enable diff --git a/cpp/autobuilder/Semmle.Autobuild.Cpp/Semmle.Autobuild.Cpp.csproj b/cpp/autobuilder/Semmle.Autobuild.Cpp/Semmle.Autobuild.Cpp.csproj index aadcc07568d..68cfef57b3d 100644 --- a/cpp/autobuilder/Semmle.Autobuild.Cpp/Semmle.Autobuild.Cpp.csproj +++ b/cpp/autobuilder/Semmle.Autobuild.Cpp/Semmle.Autobuild.Cpp.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net5.0 Semmle.Autobuild.Cpp Semmle.Autobuild.Cpp diff --git a/cpp/change-notes/2021-02-24-memset-may-be-deleted.md b/cpp/change-notes/2021-02-24-memset-may-be-deleted.md new file mode 100644 index 00000000000..3c6ec850ca6 --- /dev/null +++ b/cpp/change-notes/2021-02-24-memset-may-be-deleted.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* A new query (`cpp/memset-may-be-deleted`) is added to the default query suite. The query finds calls to `memset` that may be removed by the compiler. This behavior can make information-leak vulnerabilities easier to exploit. This query was originally [submitted as an experimental query by @ihsinme](https://github.com/github/codeql/pull/4953). diff --git a/cpp/change-notes/2021-03-01-fluent-interface-data-flow.md b/cpp/change-notes/2021-03-01-fluent-interface-data-flow.md new file mode 100644 index 00000000000..f1492afcf31 --- /dev/null +++ b/cpp/change-notes/2021-03-01-fluent-interface-data-flow.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* The data-flow library now recognises more side-effects of method chaining (e.g. `someObject.setX(clean).setY(tainted).setZ...` having a side-effect on `someObject`), as well as other related circumstances where a function input is directly passed to its output. All queries that use data-flow analysis, including most security queries, may return more results accordingly. diff --git a/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted-bad.c b/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted-bad.c new file mode 100644 index 00000000000..ac74314eefa --- /dev/null +++ b/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted-bad.c @@ -0,0 +1,3 @@ +char password[MAX_PASSWORD_LENGTH]; +// read and verify password +memset(password, 0, MAX_PASSWORD_LENGTH); diff --git a/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted-good.c b/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted-good.c new file mode 100644 index 00000000000..2e72f553a4e --- /dev/null +++ b/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted-good.c @@ -0,0 +1,3 @@ +char password[MAX_PASSWORD_LENGTH]; +// read and verify password +memset_s(password, MAX_PASSWORD_LENGTH, 0, MAX_PASSWORD_LENGTH); diff --git a/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.qhelp b/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.qhelp new file mode 100644 index 00000000000..2c087e37eaa --- /dev/null +++ b/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.qhelp @@ -0,0 +1,45 @@ + + + +

Calling memset or bzero on a buffer to clear its contents may get optimized +away by the compiler if the buffer is not subsequently used. This is not desirable behavior if the buffer +contains sensitive data that could somehow be retrieved by an attacker.

+ +
+ + +

Use alternative platform-supplied functions that will not get optimized away. Examples of such +functions include memset_s, SecureZeroMemory, and bzero_explicit. +Alternatively, passing the -fno-builtin-memset option to the GCC/Clang compiler usually +also prevents the optimization. Finally, you can use the public-domain secure_memzero function +(see references below). This function, however, is not guaranteed to work on all platforms and compilers.

+ +
+ +

The following program fragment uses memset to erase sensitive information after it is no +longer needed:

+ +

Because of dead store elimination, the call to memset may be removed by the compiler +(since the buffer is not subsequently used), resulting in potentially sensitive data remaining in memory. +

+ +

The best solution to this problem is to use the memset_s function instead of +memset:

+ + +
+ + +
  • +CERT C Coding Standard: +MSC06-C. Beware of compiler optimizations. +
  • +
  • +USENIX: The Advanced Computing Systems Association: +Dead Store Elimination (Still) Considered Harmfuls +
  • + +
    +
    diff --git a/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.ql b/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.ql new file mode 100644 index 00000000000..df6a614079e --- /dev/null +++ b/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.ql @@ -0,0 +1,66 @@ +/** + * @name Call to `memset` may be deleted + * @description Using the `memset` function to clear private data in a variable that has no subsequent use + * can make information-leak vulnerabilities easier to exploit because the compiler can remove the call. + * @kind problem + * @id cpp/memset-may-be-deleted + * @problem.severity warning + * @precision high + * @tags security + * external/cwe/cwe-14 + */ + +import cpp +import semmle.code.cpp.dataflow.EscapesTree +import semmle.code.cpp.commons.Exclusions +import semmle.code.cpp.models.interfaces.Alias + +class MemsetFunction extends Function { + MemsetFunction() { + this.hasGlobalOrStdOrBslName("memset") + or + this.hasGlobalOrStdName("wmemset") + or + this.hasGlobalName(["bzero", "__builtin_memset"]) + } +} + +predicate isNonEscapingArgument(Expr escaped) { + exists(Call call, AliasFunction aliasFunction, int i | + aliasFunction = call.getTarget() and + call.getArgument(i) = escaped.getUnconverted() and + ( + aliasFunction.parameterNeverEscapes(i) + or + aliasFunction.parameterEscapesOnlyViaReturn(i) and + (call instanceof ExprInVoidContext or call.getConversion*() instanceof BoolConversion) + ) + ) +} + +from FunctionCall call, LocalVariable v, MemsetFunction memset +where + call.getTarget() = memset and + not isFromMacroDefinition(call) and + // `v` escapes as the argument to `memset` + variableAddressEscapesTree(v.getAnAccess(), call.getArgument(0).getFullyConverted()) and + // ... and `v` doesn't escape anywhere else. + forall(Expr escape | variableAddressEscapesTree(v.getAnAccess(), escape) | + isNonEscapingArgument(escape) + ) and + not v.isStatic() and + // Reference-typed variables get special treatment in `variableAddressEscapesTree` so we leave them + // out of this query. + not v.getUnspecifiedType() instanceof ReferenceType and + // `v` is not only just used in the call to `memset`. + exists(Access acc | + acc = v.getAnAccess() and not call.getArgument(0).getAChild*() = acc and not acc.isUnevaluated() + ) and + // There is no later use of `v`. + not v.getAnAccess() = call.getASuccessor*() and + // Not using the `-fno-builtin-memset` flag + exists(Compilation c | + c.getAFileCompiled() = call.getFile() and + not c.getAnArgument() = "-fno-builtin-memset" + ) +select call, "Call to " + memset.getName() + " may be deleted by the compiler." diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c deleted file mode 100644 index 14dd07a573e..00000000000 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c +++ /dev/null @@ -1,35 +0,0 @@ -// BAD: the memset call will probably be removed. -void getPassword(void) { - char pwd[64]; - if (GetPassword(pwd, sizeof(pwd))) { - /* Checking of password, secure operations, etc. */ - } - memset(pwd, 0, sizeof(pwd)); -} -// GOOD: in this case the memset will not be removed. -void getPassword(void) { - char pwd[64]; - - if (retrievePassword(pwd, sizeof(pwd))) { - /* Checking of password, secure operations, etc. */ - } - memset_s(pwd, 0, sizeof(pwd)); -} -// GOOD: in this case the memset will not be removed. -void getPassword(void) { - char pwd[64]; - if (retrievePassword(pwd, sizeof(pwd))) { - /* Checking of password, secure operations, etc. */ - } - SecureZeroMemory(pwd, sizeof(pwd)); -} -// GOOD: in this case the memset will not be removed. -void getPassword(void) { - char pwd[64]; - if (retrievePassword(pwd, sizeof(pwd))) { - /* Checking of password, secure operations, etc. */ - } -#pragma optimize("", off) - memset(pwd, 0, sizeof(pwd)); -#pragma optimize("", on) -} diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp deleted file mode 100644 index df0ed151d8f..00000000000 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp +++ /dev/null @@ -1,31 +0,0 @@ - - - -

    Compiler optimization will exclude the cleaning of private information. -Using the memset function to clear private data in a variable that has no subsequent use is potentially dangerous, since the compiler can remove the call. -For some compilers, optimization is also possible when using calls to free memory after the memset function.

    - -

    It is possible to miss detection of vulnerabilities if used to clear fields of structures or parts of a buffer.

    - -
    - - -

    We recommend to use the RtlSecureZeroMemory or memset_s functions, or compilation flags that exclude optimization of memset calls (e.g. -fno-builtin-memset).

    - -
    - -

    The following example demonstrates an erroneous and corrected use of the memset function.

    - - -
    - - -
  • - CERT C Coding Standard: - MSC06-C. Beware of compiler optimizations. -
  • - -
    -
    diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql deleted file mode 100644 index db09de9430d..00000000000 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql +++ /dev/null @@ -1,127 +0,0 @@ -/** - * @name Compiler Removal Of Code To Clear Buffers - * @description Using memset the function to clear private data in a variable that has no subsequent use - * is potentially dangerous because the compiler can remove the call. - * @kind problem - * @id cpp/compiler-removal-of-code-to-clear-buffers - * @problem.severity warning - * @precision medium - * @tags security - * external/cwe/cwe-14 - */ - -import cpp -import semmle.code.cpp.dataflow.DataFlow -import semmle.code.cpp.dataflow.StackAddress - -/** - * A call to `memset` of the form `memset(ptr, value, num)`, for some local variable `ptr`. - */ -class CompilerRemovaMemset extends FunctionCall { - CompilerRemovaMemset() { - this.getTarget().hasGlobalOrStdName("memset") and - exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Expr exp | - DataFlow::localFlow(source, sink) and - this.getArgument(0) = isv.getAnAccess() and - ( - source.asExpr() = exp - or - // handle the case where exp is defined by an address being passed into some function. - source.asDefiningArgument() = exp - ) and - exp.getLocation().getEndLine() < this.getArgument(0).getLocation().getStartLine() and - sink.asExpr() = this.getArgument(0) - ) - } - - predicate isExistsAllocForThisVariable() { - exists(AllocationExpr alloc, Variable v | - alloc = v.getAnAssignedValue() and - this.getArgument(0) = v.getAnAccess() and - alloc.getASuccessor+() = this - ) - or - not stackPointerFlowsToUse(this.getArgument(0), _, _, _) - } - - predicate isExistsFreeForThisVariable() { - exists(DeallocationExpr free, Variable v | - this.getArgument(0) = v.getAnAccess() and - free.getFreedExpr() = v.getAnAccess() and - this.getASuccessor+() = free - ) - } - - predicate isExistsCallWithThisVariableExcludingDeallocationCalls() { - exists(FunctionCall fc, Variable v | - not fc instanceof DeallocationExpr and - this.getArgument(0) = v.getAnAccess() and - fc.getAnArgument() = v.getAnAccess() and - this.getASuccessor+() = fc - ) - } - - predicate isVariableUseAfterMemsetExcludingCalls() { - exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Expr exp | - DataFlow::localFlow(source, sink) and - this.getArgument(0) = isv.getAnAccess() and - source.asExpr() = isv.getAnAccess() and - exp.getLocation().getStartLine() > this.getArgument(2).getLocation().getEndLine() and - not exp.getParent() instanceof FunctionCall and - sink.asExpr() = exp - ) - } - - predicate isVariableUseBoundWithArgumentFunction() { - exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Parameter p, Expr exp | - DataFlow::localFlow(source, sink) and - this.getArgument(0) = isv.getAnAccess() and - this.getEnclosingFunction().getAParameter() = p and - exp.getAChild*() = p.getAnAccess() and - source.asExpr() = exp and - sink.asExpr() = isv.getAnAccess() - ) - } - - predicate isVariableUseBoundWithGlobalVariable() { - exists( - DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, GlobalVariable gv, Expr exp - | - DataFlow::localFlow(source, sink) and - this.getArgument(0) = isv.getAnAccess() and - exp.getAChild*() = gv.getAnAccess() and - source.asExpr() = exp and - sink.asExpr() = isv.getAnAccess() - ) - } - - predicate isExistsCompilationFlagsBlockingRemoval() { - exists(Compilation c | - c.getAFileCompiled() = this.getFile() and - c.getAnArgument() = "-fno-builtin-memset" - ) - } - - predicate isUseVCCompilation() { - exists(Compilation c | - c.getAFileCompiled() = this.getFile() and - ( - c.getArgument(2).matches("%gcc%") or - c.getArgument(2).matches("%g++%") or - c.getArgument(2).matches("%clang%") or - c.getArgument(2) = "--force-recompute" - ) - ) - } -} - -from CompilerRemovaMemset fc -where - not (fc.isExistsAllocForThisVariable() and not fc.isExistsFreeForThisVariable()) and - not (fc.isExistsFreeForThisVariable() and not fc.isUseVCCompilation()) and - not fc.isVariableUseAfterMemsetExcludingCalls() and - not fc.isExistsCallWithThisVariableExcludingDeallocationCalls() and - not fc.isVariableUseBoundWithArgumentFunction() and - not fc.isVariableUseBoundWithGlobalVariable() and - not fc.isExistsCompilationFlagsBlockingRemoval() -select fc.getArgument(0), "This variable will not be cleared." diff --git a/cpp/ql/src/semmle/code/cpp/Element.qll b/cpp/ql/src/semmle/code/cpp/Element.qll index 66f23ea110f..daa15e0f625 100644 --- a/cpp/ql/src/semmle/code/cpp/Element.qll +++ b/cpp/ql/src/semmle/code/cpp/Element.qll @@ -80,11 +80,9 @@ class Element extends ElementBase { File getFile() { result = this.getLocation().getFile() } /** - * Holds if this element may be from source. - * - * Note: this predicate is provided for consistency with the libraries - * for other languages, such as Java and Python. In C++, all files are - * classified as source files, so this predicate is always true. + * Holds if this element may be from source. This predicate holds for all + * elements, except for those in the dummy file, whose name is the empty string. + * The dummy file contains declarations that are built directly into the compiler. */ predicate fromSource() { this.getFile().fromSource() } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll index 1d2e9052842..54f41545284 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll @@ -415,6 +415,30 @@ private module Cached { store(node1, tc.getContent(), node2, contentType, tc.getContainerType()) } + /** + * Holds if data can flow from `fromNode` to `toNode` because they are the post-update + * nodes of some function output and input respectively, where the output and input + * are aliases. A typical example is a function returning `this`, implementing a fluent + * interface. + */ + cached + predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) { + exists(Node fromPre, Node toPre | + fromPre = fromNode.getPreUpdateNode() and + toPre = toNode.getPreUpdateNode() + | + exists(DataFlowCall c | + // Does the language-specific simpleLocalFlowStep already model flow + // from function input to output? + fromPre = getAnOutNode(c, _) and + toPre.(ArgumentNode).argumentOf(c, _) and + simpleLocalFlowStep(toPre.(ArgumentNode), fromPre) + ) + or + argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre) + ) + } + /** * Holds if the call context `call` either improves virtual dispatch in * `callable` or if it allows us to prune unreachable nodes in `callable`. diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll index 1d2e9052842..54f41545284 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll @@ -415,6 +415,30 @@ private module Cached { store(node1, tc.getContent(), node2, contentType, tc.getContainerType()) } + /** + * Holds if data can flow from `fromNode` to `toNode` because they are the post-update + * nodes of some function output and input respectively, where the output and input + * are aliases. A typical example is a function returning `this`, implementing a fluent + * interface. + */ + cached + predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) { + exists(Node fromPre, Node toPre | + fromPre = fromNode.getPreUpdateNode() and + toPre = toNode.getPreUpdateNode() + | + exists(DataFlowCall c | + // Does the language-specific simpleLocalFlowStep already model flow + // from function input to output? + fromPre = getAnOutNode(c, _) and + toPre.(ArgumentNode).argumentOf(c, _) and + simpleLocalFlowStep(toPre.(ArgumentNode), fromPre) + ) + or + argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre) + ) + } + /** * Holds if the call context `call` either improves virtual dispatch in * `callable` or if it allows us to prune unreachable nodes in `callable`. diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll index a12e35d471b..a2ce0662dc2 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll @@ -10,79 +10,32 @@ private import Imports::MemoryAccessKind private import Imports::IRType private import Imports::Overlap private import Imports::OperandTag - -cached -private newtype TOperand = - TRegisterOperand(Instruction useInstr, RegisterOperandTag tag, Instruction defInstr) { - defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and - not Construction::isInCycle(useInstr) and - strictcount(Construction::getRegisterOperandDefinition(useInstr, tag)) = 1 - } or - TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) { - useInstr.getOpcode().hasOperand(tag) - } or - TPhiOperand( - PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap - ) { - defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap) - } +private import Imports::TOperand +private import internal.OperandInternal /** - * Base class for all register operands. This is a placeholder for the IPA union type that we will - * eventually use for this purpose. + * An operand of an `Instruction` in this stage of the IR. Implemented as a union of the branches + * of `TOperand` that are used in this stage. */ -private class RegisterOperandBase extends TRegisterOperand { - /** Gets a textual representation of this element. */ - abstract string toString(); -} - -/** - * Returns the register operand with the specified parameters. - */ -private RegisterOperandBase registerOperand( - Instruction useInstr, RegisterOperandTag tag, Instruction defInstr -) { - result = TRegisterOperand(useInstr, tag, defInstr) -} - -/** - * Base class for all non-Phi memory operands. This is a placeholder for the IPA union type that we - * will eventually use for this purpose. - */ -private class NonPhiMemoryOperandBase extends TNonPhiMemoryOperand { - /** Gets a textual representation of this element. */ - abstract string toString(); -} - -/** - * Returns the non-Phi memory operand with the specified parameters. - */ -private NonPhiMemoryOperandBase nonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) { - result = TNonPhiMemoryOperand(useInstr, tag) -} - -/** - * Base class for all Phi operands. This is a placeholder for the IPA union type that we will - * eventually use for this purpose. - */ -private class PhiOperandBase extends TPhiOperand { - abstract string toString(); -} - -/** - * Returns the Phi operand with the specified parameters. - */ -private PhiOperandBase phiOperand( - Instruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap -) { - result = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) -} +private class TStageOperand = + TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand; /** * An operand of an `Instruction`. The operand represents a use of the result of one instruction * (the defining instruction) in another instruction (the use instruction) */ -class Operand extends TOperand { +class Operand extends TStageOperand { + cached + Operand() { + // Ensure that the operand does not refer to instructions from earlier stages that are unreachable here + exists(Instruction use, Instruction def | this = registerOperand(use, _, def)) or + exists(Instruction use | this = nonSSAMemoryOperand(use, _)) or + exists(Instruction use, Instruction def, IRBlock predecessorBlock | + this = phiOperand(use, def, predecessorBlock, _) + ) or + exists(Instruction use | this = chiOperand(use, _)) + } + /** Gets a textual representation of this element. */ string toString() { result = "Operand" } @@ -238,9 +191,11 @@ class Operand extends TOperand { * An operand that consumes a memory result (e.g. the `LoadOperand` on a `Load` instruction). */ class MemoryOperand extends Operand { + cached MemoryOperand() { - this instanceof NonPhiMemoryOperandBase or - this instanceof PhiOperandBase + this instanceof TNonSSAMemoryOperand or + this instanceof TPhiOperand or + this instanceof TChiOperand } /** @@ -278,7 +233,8 @@ class NonPhiOperand extends Operand { NonPhiOperand() { this = registerOperand(useInstr, tag, _) or - this = nonPhiMemoryOperand(useInstr, tag) + this = nonSSAMemoryOperand(useInstr, tag) or + this = chiOperand(useInstr, tag) } final override Instruction getUse() { result = useInstr } @@ -298,10 +254,11 @@ class NonPhiOperand extends Operand { /** * An operand that consumes a register (non-memory) result. */ -class RegisterOperand extends NonPhiOperand, RegisterOperandBase { +class RegisterOperand extends NonPhiOperand, TRegisterOperand { override RegisterOperandTag tag; Instruction defInstr; + cached RegisterOperand() { this = registerOperand(useInstr, tag, defInstr) } final override string toString() { result = tag.toString() } @@ -317,10 +274,15 @@ class RegisterOperand extends NonPhiOperand, RegisterOperandBase { /** * A memory operand other than the operand of a `Phi` instruction. */ -class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase { +class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand { override MemoryOperandTag tag; - NonPhiMemoryOperand() { this = nonPhiMemoryOperand(useInstr, tag) } + cached + NonPhiMemoryOperand() { + this = nonSSAMemoryOperand(useInstr, tag) + or + this = chiOperand(useInstr, tag) + } final override string toString() { result = tag.toString() } @@ -462,12 +424,13 @@ class SideEffectOperand extends TypedOperand { /** * An operand of a `PhiInstruction`. */ -class PhiInputOperand extends MemoryOperand, PhiOperandBase { +class PhiInputOperand extends MemoryOperand, TPhiOperand { PhiInstruction useInstr; Instruction defInstr; IRBlock predecessorBlock; Overlap overlap; + cached PhiInputOperand() { this = phiOperand(useInstr, defInstr, predecessorBlock, overlap) } override string toString() { result = "Phi" } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/OperandImports.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/OperandImports.qll index 3c781579cee..d0e013d1fba 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/OperandImports.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/OperandImports.qll @@ -2,3 +2,4 @@ import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind import semmle.code.cpp.ir.implementation.IRType as IRType import semmle.code.cpp.ir.internal.Overlap as Overlap import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag +import semmle.code.cpp.ir.implementation.internal.TOperand as TOperand diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/OperandInternal.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/OperandInternal.qll new file mode 100644 index 00000000000..b47c20e97ef --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/OperandInternal.qll @@ -0,0 +1,2 @@ +private import semmle.code.cpp.ir.implementation.internal.TOperand +import AliasedSSAOperands diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll index 8e904ee6bc4..a1c970121d2 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll @@ -6,6 +6,7 @@ private import Imports::Overlap private import Imports::TInstruction private import Imports::RawIR as RawIR private import SSAInstructions +private import SSAOperands private import NewIR private class OldBlock = Reachability::ReachableBlock; diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstructionImports.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstructionImports.qll index f347df86ba1..219180d9f4d 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstructionImports.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstructionImports.qll @@ -3,3 +3,4 @@ import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag import semmle.code.cpp.ir.internal.Overlap as Overlap import semmle.code.cpp.ir.implementation.internal.TInstruction as TInstruction import semmle.code.cpp.ir.implementation.raw.IR as RawIR +import semmle.code.cpp.ir.implementation.internal.TOperand as TOperand diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstructionInternal.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstructionInternal.qll index bb068bdd489..a1ce2629cc2 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstructionInternal.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstructionInternal.qll @@ -5,3 +5,4 @@ import semmle.code.cpp.ir.implementation.aliased_ssa.IR as NewIR import semmle.code.cpp.ir.implementation.internal.TInstruction::AliasedSSAInstructions as SSAInstructions import semmle.code.cpp.ir.internal.IRCppLanguage as Language import AliasedSSA as Alias +import semmle.code.cpp.ir.implementation.internal.TOperand::AliasedSSAOperands as SSAOperands diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TOperand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TOperand.qll new file mode 100644 index 00000000000..1e132463cdd --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TOperand.qll @@ -0,0 +1,180 @@ +private import TInstruction +private import OperandTag +private import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as RawConstruction +private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as UnaliasedConstruction +private import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SSAConstruction as AliasedConstruction +private import semmle.code.cpp.ir.implementation.raw.IR as Raw +private import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as Unaliased +private import semmle.code.cpp.ir.implementation.aliased_ssa.IR as Aliased +private import semmle.code.cpp.ir.internal.Overlap + +/** + * Provides the newtype used to represent operands across all phases of the IR. + */ +private module Internal { + /** + * An IR operand. `TOperand` is shared across all phases of the IR. There are branches of this + * type for operands created directly from the AST (`TRegisterOperand` and `TNonSSAMemoryOperand`), + * for operands computed by each stage of SSA construction (`T*PhiOperand` and + * `TAliasedChiOperand`), and a placehold branch for operands that do not exist in a given + * stage of IR construction (`TNoOperand`). + */ + cached + newtype TOperand = + // RAW + TRegisterOperand(TRawInstruction useInstr, RegisterOperandTag tag, TRawInstruction defInstr) { + defInstr = RawConstruction::getRegisterOperandDefinition(useInstr, tag) and + not RawConstruction::isInCycle(useInstr) and + strictcount(RawConstruction::getRegisterOperandDefinition(useInstr, tag)) = 1 + } or + // Placeholder for Phi and Chi operands in stages that don't have the corresponding instructions + TNoOperand() { none() } or + // Can be "removed" later when there's unreachable code + // These operands can be reused across all three stages. They just get different defs. + TNonSSAMemoryOperand(Raw::Instruction useInstr, MemoryOperandTag tag) { + // Has no definition in raw but will get definitions later + useInstr.getOpcode().hasOperand(tag) + } or + TUnaliasedPhiOperand( + Unaliased::PhiInstruction useInstr, Unaliased::Instruction defInstr, + Unaliased::IRBlock predecessorBlock, Overlap overlap + ) { + defInstr = UnaliasedConstruction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap) + } or + //// ALIASED + //// + // Until we share SSA, these will be all the phis there are. With SSA + // sharing, these will add to the ones that are already there. + // If we share SSA, be careful with the case where we remove all possible + // indirect writes to a variable because they're dead code. In that case it's + // important that we use the same definition of "is variable aliased" across + // the phases. + TAliasedPhiOperand( + TAliasedSSAPhiInstruction useInstr, Aliased::Instruction defInstr, + Aliased::IRBlock predecessorBlock, Overlap overlap + ) { + defInstr = AliasedConstruction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap) + } or + TAliasedChiOperand(TAliasedSSAChiInstruction useInstr, ChiOperandTag tag) { any() } +} + +/** + * Reexports some branches from `TOperand` so they can be used in stage modules without importing + * `TOperand` itself. + */ +private module Shared { + class TRegisterOperand = Internal::TRegisterOperand; + + /** + * Returns the register operand with the specified parameters. + */ + TRegisterOperand registerOperand( + TRawInstruction useInstr, RegisterOperandTag tag, TRawInstruction defInstr + ) { + result = Internal::TRegisterOperand(useInstr, tag, defInstr) + } + + class TNonSSAMemoryOperand = Internal::TNonSSAMemoryOperand; + + /** + * Returns the non-Phi memory operand with the specified parameters. + */ + TNonSSAMemoryOperand nonSSAMemoryOperand(TRawInstruction useInstr, MemoryOperandTag tag) { + result = Internal::TNonSSAMemoryOperand(useInstr, tag) + } +} + +/** + * Provides wrappers for the constructors of each branch of `TOperand` that is used by the + * raw IR stage. + * These wrappers are not parameterized because it is not possible to invoke an IPA constructor via + * a class alias. + */ +module RawOperands { + import Shared + + class TPhiOperand = Internal::TNoOperand; + + class TChiOperand = Internal::TNoOperand; + + class TNonPhiMemoryOperand = TNonSSAMemoryOperand or TChiOperand; + + /** + * Returns the Phi operand with the specified parameters. + */ + TPhiOperand phiOperand( + Raw::PhiInstruction useInstr, Raw::Instruction defInstr, Raw::IRBlock predecessorBlock, + Overlap overlap + ) { + none() + } + + /** + * Returns the Chi operand with the specified parameters. + */ + TChiOperand chiOperand(Raw::Instruction useInstr, ChiOperandTag tag) { none() } +} + +/** + * Provides wrappers for the constructors of each branch of `TOperand` that is used by the + * unaliased SSA stage. + * These wrappers are not parameterized because it is not possible to invoke an IPA constructor via + * a class alias. + */ +module UnaliasedSSAOperands { + import Shared + + class TPhiOperand = Internal::TUnaliasedPhiOperand; + + class TChiOperand = Internal::TNoOperand; + + class TNonPhiMemoryOperand = TNonSSAMemoryOperand or TChiOperand; + + /** + * Returns the Phi operand with the specified parameters. + */ + TPhiOperand phiOperand( + Unaliased::PhiInstruction useInstr, Unaliased::Instruction defInstr, + Unaliased::IRBlock predecessorBlock, Overlap overlap + ) { + result = Internal::TUnaliasedPhiOperand(useInstr, defInstr, predecessorBlock, overlap) + } + + /** + * Returns the Chi operand with the specified parameters. + */ + TChiOperand chiOperand(Unaliased::Instruction useInstr, ChiOperandTag tag) { none() } +} + +/** + * Provides wrappers for the constructors of each branch of `TOperand` that is used by the + * asliased SSA stage. + * These wrappers are not parameterized because it is not possible to invoke an IPA constructor via + * a class alias. + */ +module AliasedSSAOperands { + import Shared + + class TPhiOperand = Internal::TAliasedPhiOperand; + + class TChiOperand = Internal::TAliasedChiOperand; + + class TNonPhiMemoryOperand = TNonSSAMemoryOperand or TChiOperand; + + /** + * Returns the Phi operand with the specified parameters. + */ + TPhiOperand phiOperand( + TAliasedSSAPhiInstruction useInstr, Aliased::Instruction defInstr, + Aliased::IRBlock predecessorBlock, Overlap overlap + ) { + result = Internal::TAliasedPhiOperand(useInstr, defInstr, predecessorBlock, overlap) + } + + /** + * Returns the Chi operand with the specified parameters. + */ + TChiOperand chiOperand(TAliasedSSAChiInstruction useInstr, ChiOperandTag tag) { + result = Internal::TAliasedChiOperand(useInstr, tag) + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll index a12e35d471b..a2ce0662dc2 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll @@ -10,79 +10,32 @@ private import Imports::MemoryAccessKind private import Imports::IRType private import Imports::Overlap private import Imports::OperandTag - -cached -private newtype TOperand = - TRegisterOperand(Instruction useInstr, RegisterOperandTag tag, Instruction defInstr) { - defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and - not Construction::isInCycle(useInstr) and - strictcount(Construction::getRegisterOperandDefinition(useInstr, tag)) = 1 - } or - TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) { - useInstr.getOpcode().hasOperand(tag) - } or - TPhiOperand( - PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap - ) { - defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap) - } +private import Imports::TOperand +private import internal.OperandInternal /** - * Base class for all register operands. This is a placeholder for the IPA union type that we will - * eventually use for this purpose. + * An operand of an `Instruction` in this stage of the IR. Implemented as a union of the branches + * of `TOperand` that are used in this stage. */ -private class RegisterOperandBase extends TRegisterOperand { - /** Gets a textual representation of this element. */ - abstract string toString(); -} - -/** - * Returns the register operand with the specified parameters. - */ -private RegisterOperandBase registerOperand( - Instruction useInstr, RegisterOperandTag tag, Instruction defInstr -) { - result = TRegisterOperand(useInstr, tag, defInstr) -} - -/** - * Base class for all non-Phi memory operands. This is a placeholder for the IPA union type that we - * will eventually use for this purpose. - */ -private class NonPhiMemoryOperandBase extends TNonPhiMemoryOperand { - /** Gets a textual representation of this element. */ - abstract string toString(); -} - -/** - * Returns the non-Phi memory operand with the specified parameters. - */ -private NonPhiMemoryOperandBase nonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) { - result = TNonPhiMemoryOperand(useInstr, tag) -} - -/** - * Base class for all Phi operands. This is a placeholder for the IPA union type that we will - * eventually use for this purpose. - */ -private class PhiOperandBase extends TPhiOperand { - abstract string toString(); -} - -/** - * Returns the Phi operand with the specified parameters. - */ -private PhiOperandBase phiOperand( - Instruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap -) { - result = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) -} +private class TStageOperand = + TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand; /** * An operand of an `Instruction`. The operand represents a use of the result of one instruction * (the defining instruction) in another instruction (the use instruction) */ -class Operand extends TOperand { +class Operand extends TStageOperand { + cached + Operand() { + // Ensure that the operand does not refer to instructions from earlier stages that are unreachable here + exists(Instruction use, Instruction def | this = registerOperand(use, _, def)) or + exists(Instruction use | this = nonSSAMemoryOperand(use, _)) or + exists(Instruction use, Instruction def, IRBlock predecessorBlock | + this = phiOperand(use, def, predecessorBlock, _) + ) or + exists(Instruction use | this = chiOperand(use, _)) + } + /** Gets a textual representation of this element. */ string toString() { result = "Operand" } @@ -238,9 +191,11 @@ class Operand extends TOperand { * An operand that consumes a memory result (e.g. the `LoadOperand` on a `Load` instruction). */ class MemoryOperand extends Operand { + cached MemoryOperand() { - this instanceof NonPhiMemoryOperandBase or - this instanceof PhiOperandBase + this instanceof TNonSSAMemoryOperand or + this instanceof TPhiOperand or + this instanceof TChiOperand } /** @@ -278,7 +233,8 @@ class NonPhiOperand extends Operand { NonPhiOperand() { this = registerOperand(useInstr, tag, _) or - this = nonPhiMemoryOperand(useInstr, tag) + this = nonSSAMemoryOperand(useInstr, tag) or + this = chiOperand(useInstr, tag) } final override Instruction getUse() { result = useInstr } @@ -298,10 +254,11 @@ class NonPhiOperand extends Operand { /** * An operand that consumes a register (non-memory) result. */ -class RegisterOperand extends NonPhiOperand, RegisterOperandBase { +class RegisterOperand extends NonPhiOperand, TRegisterOperand { override RegisterOperandTag tag; Instruction defInstr; + cached RegisterOperand() { this = registerOperand(useInstr, tag, defInstr) } final override string toString() { result = tag.toString() } @@ -317,10 +274,15 @@ class RegisterOperand extends NonPhiOperand, RegisterOperandBase { /** * A memory operand other than the operand of a `Phi` instruction. */ -class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase { +class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand { override MemoryOperandTag tag; - NonPhiMemoryOperand() { this = nonPhiMemoryOperand(useInstr, tag) } + cached + NonPhiMemoryOperand() { + this = nonSSAMemoryOperand(useInstr, tag) + or + this = chiOperand(useInstr, tag) + } final override string toString() { result = tag.toString() } @@ -462,12 +424,13 @@ class SideEffectOperand extends TypedOperand { /** * An operand of a `PhiInstruction`. */ -class PhiInputOperand extends MemoryOperand, PhiOperandBase { +class PhiInputOperand extends MemoryOperand, TPhiOperand { PhiInstruction useInstr; Instruction defInstr; IRBlock predecessorBlock; Overlap overlap; + cached PhiInputOperand() { this = phiOperand(useInstr, defInstr, predecessorBlock, overlap) } override string toString() { result = "Phi" } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/OperandImports.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/OperandImports.qll index 3c781579cee..d0e013d1fba 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/OperandImports.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/OperandImports.qll @@ -2,3 +2,4 @@ import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind import semmle.code.cpp.ir.implementation.IRType as IRType import semmle.code.cpp.ir.internal.Overlap as Overlap import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag +import semmle.code.cpp.ir.implementation.internal.TOperand as TOperand diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/OperandInternal.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/OperandInternal.qll new file mode 100644 index 00000000000..194e21e0d93 --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/OperandInternal.qll @@ -0,0 +1,2 @@ +private import semmle.code.cpp.ir.implementation.internal.TOperand +import RawOperands diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll index a12e35d471b..a2ce0662dc2 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll @@ -10,79 +10,32 @@ private import Imports::MemoryAccessKind private import Imports::IRType private import Imports::Overlap private import Imports::OperandTag - -cached -private newtype TOperand = - TRegisterOperand(Instruction useInstr, RegisterOperandTag tag, Instruction defInstr) { - defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and - not Construction::isInCycle(useInstr) and - strictcount(Construction::getRegisterOperandDefinition(useInstr, tag)) = 1 - } or - TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) { - useInstr.getOpcode().hasOperand(tag) - } or - TPhiOperand( - PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap - ) { - defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap) - } +private import Imports::TOperand +private import internal.OperandInternal /** - * Base class for all register operands. This is a placeholder for the IPA union type that we will - * eventually use for this purpose. + * An operand of an `Instruction` in this stage of the IR. Implemented as a union of the branches + * of `TOperand` that are used in this stage. */ -private class RegisterOperandBase extends TRegisterOperand { - /** Gets a textual representation of this element. */ - abstract string toString(); -} - -/** - * Returns the register operand with the specified parameters. - */ -private RegisterOperandBase registerOperand( - Instruction useInstr, RegisterOperandTag tag, Instruction defInstr -) { - result = TRegisterOperand(useInstr, tag, defInstr) -} - -/** - * Base class for all non-Phi memory operands. This is a placeholder for the IPA union type that we - * will eventually use for this purpose. - */ -private class NonPhiMemoryOperandBase extends TNonPhiMemoryOperand { - /** Gets a textual representation of this element. */ - abstract string toString(); -} - -/** - * Returns the non-Phi memory operand with the specified parameters. - */ -private NonPhiMemoryOperandBase nonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) { - result = TNonPhiMemoryOperand(useInstr, tag) -} - -/** - * Base class for all Phi operands. This is a placeholder for the IPA union type that we will - * eventually use for this purpose. - */ -private class PhiOperandBase extends TPhiOperand { - abstract string toString(); -} - -/** - * Returns the Phi operand with the specified parameters. - */ -private PhiOperandBase phiOperand( - Instruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap -) { - result = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) -} +private class TStageOperand = + TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand; /** * An operand of an `Instruction`. The operand represents a use of the result of one instruction * (the defining instruction) in another instruction (the use instruction) */ -class Operand extends TOperand { +class Operand extends TStageOperand { + cached + Operand() { + // Ensure that the operand does not refer to instructions from earlier stages that are unreachable here + exists(Instruction use, Instruction def | this = registerOperand(use, _, def)) or + exists(Instruction use | this = nonSSAMemoryOperand(use, _)) or + exists(Instruction use, Instruction def, IRBlock predecessorBlock | + this = phiOperand(use, def, predecessorBlock, _) + ) or + exists(Instruction use | this = chiOperand(use, _)) + } + /** Gets a textual representation of this element. */ string toString() { result = "Operand" } @@ -238,9 +191,11 @@ class Operand extends TOperand { * An operand that consumes a memory result (e.g. the `LoadOperand` on a `Load` instruction). */ class MemoryOperand extends Operand { + cached MemoryOperand() { - this instanceof NonPhiMemoryOperandBase or - this instanceof PhiOperandBase + this instanceof TNonSSAMemoryOperand or + this instanceof TPhiOperand or + this instanceof TChiOperand } /** @@ -278,7 +233,8 @@ class NonPhiOperand extends Operand { NonPhiOperand() { this = registerOperand(useInstr, tag, _) or - this = nonPhiMemoryOperand(useInstr, tag) + this = nonSSAMemoryOperand(useInstr, tag) or + this = chiOperand(useInstr, tag) } final override Instruction getUse() { result = useInstr } @@ -298,10 +254,11 @@ class NonPhiOperand extends Operand { /** * An operand that consumes a register (non-memory) result. */ -class RegisterOperand extends NonPhiOperand, RegisterOperandBase { +class RegisterOperand extends NonPhiOperand, TRegisterOperand { override RegisterOperandTag tag; Instruction defInstr; + cached RegisterOperand() { this = registerOperand(useInstr, tag, defInstr) } final override string toString() { result = tag.toString() } @@ -317,10 +274,15 @@ class RegisterOperand extends NonPhiOperand, RegisterOperandBase { /** * A memory operand other than the operand of a `Phi` instruction. */ -class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase { +class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand { override MemoryOperandTag tag; - NonPhiMemoryOperand() { this = nonPhiMemoryOperand(useInstr, tag) } + cached + NonPhiMemoryOperand() { + this = nonSSAMemoryOperand(useInstr, tag) + or + this = chiOperand(useInstr, tag) + } final override string toString() { result = tag.toString() } @@ -462,12 +424,13 @@ class SideEffectOperand extends TypedOperand { /** * An operand of a `PhiInstruction`. */ -class PhiInputOperand extends MemoryOperand, PhiOperandBase { +class PhiInputOperand extends MemoryOperand, TPhiOperand { PhiInstruction useInstr; Instruction defInstr; IRBlock predecessorBlock; Overlap overlap; + cached PhiInputOperand() { this = phiOperand(useInstr, defInstr, predecessorBlock, overlap) } override string toString() { result = "Phi" } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/OperandImports.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/OperandImports.qll index 3c781579cee..d0e013d1fba 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/OperandImports.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/OperandImports.qll @@ -2,3 +2,4 @@ import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind import semmle.code.cpp.ir.implementation.IRType as IRType import semmle.code.cpp.ir.internal.Overlap as Overlap import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag +import semmle.code.cpp.ir.implementation.internal.TOperand as TOperand diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/OperandInternal.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/OperandInternal.qll new file mode 100644 index 00000000000..80e06a381a1 --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/OperandInternal.qll @@ -0,0 +1,2 @@ +private import semmle.code.cpp.ir.implementation.internal.TOperand +import UnaliasedSSAOperands diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index 8e904ee6bc4..a1c970121d2 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -6,6 +6,7 @@ private import Imports::Overlap private import Imports::TInstruction private import Imports::RawIR as RawIR private import SSAInstructions +private import SSAOperands private import NewIR private class OldBlock = Reachability::ReachableBlock; diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstructionImports.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstructionImports.qll index f347df86ba1..219180d9f4d 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstructionImports.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstructionImports.qll @@ -3,3 +3,4 @@ import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag import semmle.code.cpp.ir.internal.Overlap as Overlap import semmle.code.cpp.ir.implementation.internal.TInstruction as TInstruction import semmle.code.cpp.ir.implementation.raw.IR as RawIR +import semmle.code.cpp.ir.implementation.internal.TOperand as TOperand diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstructionInternal.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstructionInternal.qll index 73b08d1286b..70d44e03267 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstructionInternal.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstructionInternal.qll @@ -6,3 +6,4 @@ import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as RawStage import semmle.code.cpp.ir.implementation.internal.TInstruction::UnaliasedSSAInstructions as SSAInstructions import semmle.code.cpp.ir.internal.IRCppLanguage as Language import SimpleSSA as Alias +import semmle.code.cpp.ir.implementation.internal.TOperand::UnaliasedSSAOperands as SSAOperands diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected deleted file mode 100644 index 8d98d94ff46..00000000000 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected +++ /dev/null @@ -1,3 +0,0 @@ -| test.c:13:9:13:13 | buff1 | This variable will not be cleared. | -| test.c:35:9:35:13 | buff1 | This variable will not be cleared. | -| test.c:43:9:43:13 | buff1 | This variable will not be cleared. | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.qlref b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.qlref deleted file mode 100644 index 61d2a29b126..00000000000 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.qlref +++ /dev/null @@ -1 +0,0 @@ -experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/test.c deleted file mode 100644 index 221072330c3..00000000000 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/test.c +++ /dev/null @@ -1,201 +0,0 @@ -struct buffers -{ - unsigned char buff1[50]; - unsigned char *buff2; -} globalBuff1,*globalBuff2; - -unsigned char * globalBuff; -void badFunc0_0(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); -} -void nobadFunc0_0(){ - unsigned char buff1[12]; - memset(buff1,12,12); -} -void nobadFunc0_1(){ - unsigned char buff1[12]; - int i; - memset(buff1,12,12); - for(i=0;i<12;i++) - buff1[i]=13; - free(buff1); -} -void nobadFunc1_0(){ - unsigned char * buff1; - buff1 = (unsigned char *) malloc(12); - memset(buff1,12,12); -} -void badFunc1_0(){ - unsigned char * buff1; - buff1 = (unsigned char *) malloc(12); - memset(buff1,12,12); - free(buff1); -} -void badFunc1_1(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - free(buff1); -} -void nobadFunc2_0_0(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - printf(buff1); -} - -void nobadFunc2_0_1(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - printf(buff1+3); -} - -void nobadFunc2_0_2(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - printf(*buff1); -} - -void nobadFunc2_0_3(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - printf(*(buff1+3)); -} -unsigned char * nobadFunc2_0_4(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - return buff1; -} - -unsigned char * nobadFunc2_0_5(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - return buff1+3; -} -unsigned char nobadFunc2_0_6(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - return *buff1; -} - -unsigned char nobadFunc2_0_7(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - return *(buff1+3); -} -void nobadFunc2_1_0(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - if(*buff1==0) - printf("123123"); -} -void nobadFunc2_1_1(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - if(*(buff1+3)==0) - printf("123123"); -} -void nobadFunc2_1_2(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - buff1[2]=5; -} -void nobadFunc3_0(unsigned char * buffAll){ - unsigned char * buff1 = buffAll; - memset(buff1,12,12); -} -void nobadFunc3_1(unsigned char * buffAll){ - unsigned char * buff1 = buffAll+3; - memset(buff1,12,12); -} -void nobadFunc3_2(struct buffers buffAll){ - unsigned char * buff1 = buffAll.buff1; - memset(buff1,12,12); -} -void nobadFunc3_3(struct buffers buffAll){ - unsigned char * buff1 = buffAll.buff2; - memset(buff1,12,12); -} -void nobadFunc3_4(struct buffers buffAll){ - unsigned char * buff1 = buffAll.buff2+3; - memset(buff1,12,12); -} -void nobadFunc3_5(struct buffers * buffAll){ - unsigned char * buff1 = buffAll->buff1; - memset(buff1,12,12); -} -void nobadFunc3_6(struct buffers *buffAll){ - unsigned char * buff1 = buffAll->buff2; - memset(buff1,12,12); -} -void nobadFunc4(){ - unsigned char * buff1 = globalBuff; - memset(buff1,12,12); -} -void nobadFunc4_0(){ - unsigned char * buff1 = globalBuff; - memset(buff1,12,12); -} -void nobadFunc4_1(){ - unsigned char * buff1 = globalBuff+3; - memset(buff1,12,12); -} -void nobadFunc4_2(){ - unsigned char * buff1 = globalBuff1.buff1; - memset(buff1,12,12); -} -void nobadFunc4_3(){ - unsigned char * buff1 = globalBuff1.buff2; - memset(buff1,12,12); -} -void nobadFunc4_4(){ - unsigned char * buff1 = globalBuff1.buff2+3; - memset(buff1,12,12); -} -void nobadFunc4_5(){ - unsigned char * buff1 = globalBuff2->buff1; - memset(buff1,12,12); -} -void nobadFunc4_6(){ - unsigned char * buff1 = globalBuff2->buff2; - memset(buff1,12,12); -} - diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-014/MemsetMayBeDeleted.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-014/MemsetMayBeDeleted.expected new file mode 100644 index 00000000000..7b469bea894 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-014/MemsetMayBeDeleted.expected @@ -0,0 +1,3 @@ +| test.cpp:48:5:48:10 | call to memset | Call to memset may be deleted by the compiler. | +| test.cpp:79:5:79:10 | call to memset | Call to memset may be deleted by the compiler. | +| test.cpp:208:2:208:7 | call to memset | Call to memset may be deleted by the compiler. | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-014/MemsetMayBeDeleted.qlref b/cpp/ql/test/query-tests/Security/CWE/CWE-014/MemsetMayBeDeleted.qlref new file mode 100644 index 00000000000..e81526fe6d9 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-014/MemsetMayBeDeleted.qlref @@ -0,0 +1 @@ +Security/CWE/CWE-014/MemsetMayBeDeleted.ql diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-014/test.c b/cpp/ql/test/query-tests/Security/CWE/CWE-014/test.c new file mode 100644 index 00000000000..1ca22b5782e --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-014/test.c @@ -0,0 +1,140 @@ +typedef unsigned long long size_t; +void *memset(void *s, int c, unsigned long n); +void *__builtin_memset(void *s, int c, unsigned long n); +typedef int errno_t; +typedef unsigned int rsize_t; +errno_t memset_s(void *dest, rsize_t destsz, int ch, rsize_t count); +char *strcpy(char *dest, const char *src); + +extern void use_pw(char *pw); + +#define PW_SIZE 32 + +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.14 (WINE): deleted +int func1(void) { + char pw1[PW_SIZE]; + use_pw(pw1); + memset(pw1, 0, PW_SIZE); // BAD [NOT DETECTED] + return 0; +} + +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.14 (WINE): not deleted +int func1a(void) { + char pw1a[PW_SIZE]; + use_pw(pw1a); + __builtin_memset(pw1a, 0, PW_SIZE); // BAD [NOT DETECTED] + return 0; +} + +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.14 (WINE): deleted +char *func1b(void) { + char pw1b[PW_SIZE]; + use_pw(pw1b); + memset(pw1b, 0, PW_SIZE); // BAD [NOT DETECTED] + pw1b[0] = pw1b[3] = 'a'; + return 0; +} + +// x86-64 gcc 9.2: not deleted +// x86-64 clang 9.0.0: not deleted +// x64 msvc v19.14 (WINE): not deleted +int func1c(char pw1c[PW_SIZE]) { + use_pw(pw1c); + memset(pw1c, 0, PW_SIZE); // GOOD + return 0; +} + +// x86-64 gcc 9.2: not deleted +// x86-64 clang 9.0.0: not deleted +// x64 msvc v19.14 (WINE): not deleted +char pw1d[PW_SIZE]; +int func1d() { + use_pw(pw1d); + memset(pw1d, 0, PW_SIZE); // GOOD + return 0; +} +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.14 (WINE): deleted +char *func2(void) { + char pw2[PW_SIZE]; + use_pw(pw2); + memset(pw2, 1, PW_SIZE); // BAD [NOT DETECTED] + return pw2; +} + +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.14 (WINE): partially deleted +int func3(void) { + char pw3[PW_SIZE]; + use_pw(pw3); + memset(pw3, 4, PW_SIZE); // BAD [NOT DETECTED] + return pw3[2]; +} + +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.14 (WINE): not deleted +int func4(void) { + char pw1a[PW_SIZE]; + use_pw(pw1a); + __builtin_memset(pw1a + 3, 0, PW_SIZE - 3); // BAD [NOT DETECTED] + return 0; +} + +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.14 (WINE): not deleted +int func6(void) { + char pw1a[PW_SIZE]; + use_pw(pw1a); + __builtin_memset(&pw1a[3], 0, PW_SIZE - 3); // BAD [NOT DETECTED] + return pw1a[2]; +} + +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.14 (WINE): not deleted +int func5(void) { + char pw1a[PW_SIZE]; + use_pw(pw1a); + __builtin_memset(pw1a + 3, 0, PW_SIZE - 4); // GOOD + return pw1a[4]; +} + +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.14 (WINE): not deleted +int func7(void) { + char pw1a[PW_SIZE]; + use_pw(pw1a); + __builtin_memset(&pw1a[3], 0, PW_SIZE - 5); // BAD [NOT DETECTED] + return 0; +} + +// x86-64 gcc 9.2: not deleted +// x86-64 clang 9.0.0: not deleted +// x64 msvc v19.14 (WINE): not deleted +int func8(void) { + char pw1a[PW_SIZE]; + use_pw(pw1a); + __builtin_memset(pw1a + pw1a[3], 0, PW_SIZE - 4); // GOOD + return pw1a[4]; +} + +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.14 (WINE): deleted +char *func9(void) { + char pw1[PW_SIZE]; + use_pw(pw1); + memset(pw1, 0, PW_SIZE); // BAD [NOT DETECTED] + return 0; +} diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-014/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-014/test.cpp new file mode 100644 index 00000000000..1e0ed7d70f0 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-014/test.cpp @@ -0,0 +1,401 @@ +extern "C" { + typedef unsigned long long size_t; + void *memset(void *s, int c, unsigned long n); + void *__builtin_memset(void *s, int c, unsigned long n); + typedef int errno_t; + typedef unsigned int rsize_t; + errno_t memset_s(void *dest, rsize_t destsz, int ch, rsize_t count); + char *strcpy(char *dest, const char *src); + void *memcpy(void *dest, const void *src, unsigned long n); + void *malloc(unsigned long size); + void free(void *ptr); + extern void use_pw(char *pw); + int printf(const char* format, ...); + char* gets(char * str); +} + +#define PW_SIZE 32 + +struct mem { + int a; + char b[PW_SIZE]; + int c; +}; + +// x86-64 gcc 9.2: not deleted +// x86-64 clang 9.0.0: not deleted +// x64 msvc v19.22: not deleted +void func(char buff[128], unsigned long long sz) { + gets(buff); + memset(buff, 0, PW_SIZE); // GOOD +} + +// x86-64 gcc 9.2: not deleted +// x86-64 clang 9.0.0: not deleted +// x64 msvc v19.22: not deleted +char *func2(char buff[128], unsigned long long sz) { + gets(buff); + memset(buff, 0, PW_SIZE); // GOOD + return buff; +} + +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.22: deleted +void func3(unsigned long long sz) { + char buff[128]; + gets(buff); + memset(buff, 0, PW_SIZE); // BAD +} + +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.22: deleted +void func4(unsigned long long sz) { + char buff[128]; + gets(buff); + memset(buff, 0, PW_SIZE); // BAD [NOT DETECTED] + strcpy(buff, "Hello"); +} + +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.22: deleted +void func5(unsigned long long sz) { + char buff[128]; + gets(buff); + memset(buff, 0, PW_SIZE); // BAD [NOT DETECTED] + if (sz > 5) { + strcpy(buff, "Hello"); + } +} + +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.22: deleted +void func6(unsigned long long sz) { + struct mem m; + gets(m.b); + memset(&m, 0, PW_SIZE); // BAD +} + +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.22: deleted +void func7(unsigned long long sz) { + struct mem m; + gets(m.b); + memset(&m, 0, PW_SIZE); // BAD [NOT DETECTED] + m.a = 15; +} + +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.22: not deleted +void func8(unsigned long long sz) { + struct mem *m = (struct mem *)malloc(sizeof(struct mem)); + gets(m->b); + memset(m, 0, PW_SIZE); // BAD [NOT DETECTED] +} + +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.22: not deleted +void func9(unsigned long long sz) { + struct mem *m = (struct mem *)malloc(sizeof(struct mem)); + gets(m->b); + memset(m, 0, PW_SIZE); // BAD [NOT DETECTED] + free(m); +} + +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.22: not deleted +void func10(unsigned long long sz) { + struct mem *m = (struct mem *)malloc(sizeof(struct mem)); + gets(m->b); + memset(m, 0, PW_SIZE); // BAD [NOT DETECTED] + m->a = sz; + m->c = m->a + 1; +} + +// x86-64 gcc 9.2: deleted +// x86-64 clang 9.0.0: deleted +// x64 msvc v19.22: not deleted +void func11(unsigned long long sz) { + struct mem *m = (struct mem *)malloc(sizeof(struct mem)); + gets(m->b); + ::memset(m, 0, PW_SIZE); // BAD [NOT DETECTED] + if (sz > 5) { + strcpy(m->b, "Hello"); + } +} + +// x86-64 gcc 9.2: not deleted +// x86-64 clang 9.0.0: not deleted +// x64 msvc v19.22: not deleted +int func12(unsigned long long sz) { + struct mem *m = (struct mem *)malloc(sizeof(struct mem)); + gets(m->b); + memset(m, 0, sz); // GOOD + return m->c; +} + +int funcN1() { + char pw[PW_SIZE]; + gets(pw); + char *pw_ptr = pw; + memset(pw, 0, PW_SIZE); // GOOD + use_pw(pw_ptr); + return 0; +} + +char pw_global[PW_SIZE]; +int funcN2() { + gets(pw_global); + use_pw(pw_global); + memset(pw_global, 0, PW_SIZE); // GOOD + return 0; +} + +int funcN3(unsigned long long sz) { + struct mem m; + gets(m.b); + memset(&m, 0, sizeof(m)); // GOOD + return m.a; +} + +void funcN(int num) { + char pw[PW_SIZE]; + int i; + for (i = 0; i < num; i++) + { + gets(pw); + use_pw(pw); + memset(pw, 0, PW_SIZE); // GOOD + } +} + +class MyClass +{ +public: + void set(int _x) { + x = _x; + } + + int get() + { + return x; + } + + void clear1() { + memset(&x, 0, sizeof(x)); // GOOD + } + + void clear2() { + memset(&(this->x), 0, sizeof(this->x)); // GOOD + } + +private: + int x; +}; + +void badFunc0_0(){ + unsigned char buff1[PW_SIZE]; + for(int i = 0; i < PW_SIZE; i++) { + buff1[i] = 13; + } + memset(buff1, 0, PW_SIZE); // BAD +} + +void nobadFunc1_0() { + char* buff1 = (char *) malloc(PW_SIZE); + gets(buff1); + memset(buff1, 0, PW_SIZE); // BAD [NOT DETECTED] +} +void badFunc1_0(){ + char * buff1 = (char *) malloc(PW_SIZE); + gets(buff1); + memset(buff1, 0, PW_SIZE); // BAD [NOT DETECTED] + free(buff1); +} +void badFunc1_1(){ + unsigned char buff1[PW_SIZE]; + for(int i = 0; i < PW_SIZE; i++) { + buff1[i] = 'a' + i; + } + memset(buff1, 0, PW_SIZE); // BAD [NOT DETECTED] + free(buff1); +} +void nobadFunc2_0_0(){ + unsigned char buff1[PW_SIZE]; + buff1[sizeof(buff1) - 1] = '\0'; + memset(buff1, 0, PW_SIZE); // GOOD + printf("%s", buff1); +} + +void nobadFunc2_0_1(){ + char buff1[PW_SIZE]; + gets(buff1); + memset(buff1, '\0', sizeof(buff1)); + memset(buff1, 0, PW_SIZE); // GOOD + printf("%s", buff1 + 3); +} + +void nobadFunc2_0_2(){ + char buff1[PW_SIZE]; + gets(buff1); + memset(buff1, 0, PW_SIZE); // GOOD + printf("%c", *buff1); +} + +void nobadFunc2_0_3(char ch){ + unsigned char buff1[PW_SIZE]; + for(int i = 0; i < PW_SIZE; i++) { + buff1[i] = ch; + } + memset(buff1, 0, PW_SIZE); // GOOD + printf("%c", *(buff1 + 3)); +} + +char * nobadFunc2_0_4(){ + char buff1[PW_SIZE]; + gets(buff1); + memset(buff1, 0, PW_SIZE); // GOOD + return buff1; +} + +char * nobadFunc2_0_5(){ + char buff1[PW_SIZE]; + gets(buff1); + memset(buff1, 0, PW_SIZE); // GOOD + + return buff1+3; +} + +unsigned char nobadFunc2_0_6(){ + unsigned char buff1[PW_SIZE]; + buff1[0] = 'z'; + int i; + memset(buff1, 0, PW_SIZE); // GOOD + + return *buff1; +} + +unsigned char nobadFunc2_0_7(){ + char buff1[PW_SIZE]; + gets(buff1); + memset(buff1, 0, PW_SIZE); // GOOD + + return *(buff1 + 3); +} + +bool nobadFunc2_1_0(unsigned char ch){ + char buff1[PW_SIZE]; + gets(buff1); + memset(buff1, 0, PW_SIZE); // GOOD + if(*buff1 == ch) { return true; } + return false; +} + +void nobadFunc2_1_2(){ + char buff1[PW_SIZE]; + gets(buff1); + memset(buff1, 0, PW_SIZE); // BAD [NOT DETECTED] + buff1[2] = 5; +} + +void nobadFunc3_0(char * buffAll){ + char * buff1 = buffAll; + gets(buff1); + memset(buff1, 0, PW_SIZE); // GOOD +} + +void nobadFunc3_1(unsigned char * buffAll){ + unsigned char * buff1 = buffAll + 3; + memset(buff1, 0, PW_SIZE); // GOOD +} + +struct buffers +{ + char buff1[50]; + unsigned char *buff2; +}; + +void nobadFunc3_2(struct buffers buffAll) { + char * buff1 = buffAll.buff1; + gets(buff1); + memset(buff1, 0, PW_SIZE); // GOOD +} + +void nobadFunc3_3(struct buffers buffAll) { + unsigned char * buff1 = buffAll.buff2; + memset(buff1, 0, PW_SIZE); // GOOD +} + +void nobadFunc3_4(struct buffers buffAll) { + unsigned char * buff1 = buffAll.buff2 + 3; + memset(buff1, 0, PW_SIZE); // GOOD +} + +void nobadFunc3_5(struct buffers * buffAll) { + char * buff1 = buffAll->buff1; + memset(buff1, 0, PW_SIZE); // GOOD +} + +void nobadFunc3_6(struct buffers *buffAll){ + unsigned char * buff1 = buffAll->buff2; + memset(buff1, 0, PW_SIZE); // GOOD +} + +char * globalBuff; + +void nobadFunc4(){ + char * buff1 = globalBuff; + memset(buff1, 0, PW_SIZE); // GOOD +} + +void nobadFunc4_0(){ + char * buff1 = globalBuff; + gets(buff1); + memset(buff1, 0, PW_SIZE); // GOOD +} +void nobadFunc4_1(){ + char * buff1 = globalBuff + 3; + memset(buff1, 0, PW_SIZE); // GOOD +} + +buffers globalBuff1, *globalBuff2; + +void nobadFunc4_2(){ + char * buff1 = globalBuff1.buff1; + memset(buff1, 0, PW_SIZE); // GOOD +} + +void nobadFunc4_3(){ + unsigned char * buff1 = globalBuff1.buff2; + memset(buff1, 0, PW_SIZE); // GOOD +} + +void nobadFunc4_4(){ + unsigned char * buff1 = globalBuff1.buff2+3; + memset(buff1, 0, PW_SIZE); // GOOD +} + +void nobadFunc4_5(){ + char * buff1 = globalBuff2->buff1; + memset(buff1, 0, PW_SIZE); // GOOD +} + +void nobadFunc4_6(){ + unsigned char * buff1 = globalBuff2->buff2; + memset(buff1, 0, PW_SIZE); // GOOD +} + +extern void use_byte(unsigned char); + +void test_static_func() { + static unsigned char buffer[PW_SIZE] = {0}; + use_byte(buffer[0]); + memset(buffer, 42, sizeof(buffer)); // GOOD +} diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/Semmle.Autobuild.CSharp.Tests.csproj b/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/Semmle.Autobuild.CSharp.Tests.csproj index ee3324eb639..64e25a8eb64 100644 --- a/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/Semmle.Autobuild.CSharp.Tests.csproj +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/Semmle.Autobuild.CSharp.Tests.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 false win-x64;linux-x64;osx-x64 enable diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp/Semmle.Autobuild.CSharp.csproj b/csharp/autobuilder/Semmle.Autobuild.CSharp/Semmle.Autobuild.CSharp.csproj index 82ca05504bc..b02b1a3fef1 100644 --- a/csharp/autobuilder/Semmle.Autobuild.CSharp/Semmle.Autobuild.CSharp.csproj +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp/Semmle.Autobuild.CSharp.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net5.0 Semmle.Autobuild.CSharp Semmle.Autobuild.CSharp diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/BuildActions.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/BuildActions.cs index b9a5c9c17c3..b75c6413e61 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/BuildActions.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/BuildActions.cs @@ -170,6 +170,10 @@ namespace Semmle.Autobuild.Shared { var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment, false); using var p = Process.Start(pi); + if (p is null) + { + return -1; + } p.WaitForExit(); return p.ExitCode; } diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/BuildTools.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/BuildTools.cs index 79367c90d8e..a598e6480f3 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/BuildTools.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/BuildTools.cs @@ -84,7 +84,7 @@ namespace Semmle.Autobuild.Shared /// /// The solution file. /// A compatible file, or throws an exception. - public static VcVarsBatFile FindCompatibleVcVars(IBuildActions actions, ISolution sln) => + public static VcVarsBatFile? FindCompatibleVcVars(IBuildActions actions, ISolution sln) => FindCompatibleVcVars(actions, sln.ToolsVersion.Major); /// @@ -92,9 +92,9 @@ namespace Semmle.Autobuild.Shared /// /// The tools version. /// A compatible file, or null. - public static VcVarsBatFile FindCompatibleVcVars(IBuildActions actions, int targetVersion) => - targetVersion < 10 ? - VcVarsAllBatFiles(actions).OrderByDescending(b => b.ToolsVersion).FirstOrDefault() : - VcVarsAllBatFiles(actions).Where(b => b.ToolsVersion >= targetVersion).OrderBy(b => b.ToolsVersion).FirstOrDefault(); + public static VcVarsBatFile? FindCompatibleVcVars(IBuildActions actions, int targetVersion) => + targetVersion < 10 + ? VcVarsAllBatFiles(actions).OrderByDescending(b => b.ToolsVersion).FirstOrDefault() + : VcVarsAllBatFiles(actions).Where(b => b.ToolsVersion >= targetVersion).OrderBy(b => b.ToolsVersion).FirstOrDefault(); } } diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/Project.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/Project.cs index aaaa7cdac56..bdc712d6623 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/Project.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/Project.cs @@ -47,7 +47,7 @@ namespace Semmle.Autobuild.Shared var root = projFile.DocumentElement; - if (root.Name == "Project") + if (root?.Name == "Project") { if (root.HasAttribute("Sdk")) { @@ -77,10 +77,17 @@ namespace Semmle.Autobuild.Shared // `` and `` is valid var mgr = new XmlNamespaceManager(projFile.NameTable); mgr.AddNamespace("msbuild", "http://schemas.microsoft.com/developer/msbuild/2003"); - var projectFileIncludes = root.SelectNodes("//msbuild:Project/msbuild:ItemGroup/msbuild:ProjectFile/@Include", mgr).OfType(); - var projectFilesIncludes = root.SelectNodes("//msbuild:Project/msbuild:ItemGroup/msbuild:ProjectFiles/@Include", mgr).OfType(); + var projectFileIncludes = root.SelectNodes("//msbuild:Project/msbuild:ItemGroup/msbuild:ProjectFile/@Include", mgr) + ?.OfType() ?? Array.Empty(); + var projectFilesIncludes = root.SelectNodes("//msbuild:Project/msbuild:ItemGroup/msbuild:ProjectFiles/@Include", mgr) + ?.OfType() ?? Array.Empty(); foreach (var include in projectFileIncludes.Concat(projectFilesIncludes)) { + if (include?.Value is null) + { + continue; + } + var includePath = builder.Actions.PathCombine(include.Value.Split('\\', StringSplitOptions.RemoveEmptyEntries)); ret.Add(new Project(builder, builder.Actions.PathCombine(DirectoryName, includePath))); } diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/Semmle.Autobuild.Shared.csproj b/csharp/autobuilder/Semmle.Autobuild.Shared/Semmle.Autobuild.Shared.csproj index 6663c428b03..5f59b205527 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/Semmle.Autobuild.Shared.csproj +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/Semmle.Autobuild.Shared.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net5.0 Semmle.Autobuild.Shared Semmle.Autobuild.Shared false diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/Solution.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/Solution.cs index c5d65794fb5..5e501a8eb99 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/Solution.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/Solution.cs @@ -90,7 +90,7 @@ namespace Semmle.Autobuild.Shared .Select(p => p.ToolsVersion); public Version ToolsVersion => ToolsVersions.Any() - ? ToolsVersions.Max() + ? ToolsVersions.Max()! : new Version(); } } diff --git a/csharp/change-notes/2021-03-01-fluent-interface-data-flow.md b/csharp/change-notes/2021-03-01-fluent-interface-data-flow.md new file mode 100644 index 00000000000..f1492afcf31 --- /dev/null +++ b/csharp/change-notes/2021-03-01-fluent-interface-data-flow.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* The data-flow library now recognises more side-effects of method chaining (e.g. `someObject.setX(clean).setY(tainted).setZ...` having a side-effect on `someObject`), as well as other related circumstances where a function input is directly passed to its output. All queries that use data-flow analysis, including most security queries, may return more results accordingly. diff --git a/csharp/change-notes/2021-03-02-dotnet5.md b/csharp/change-notes/2021-03-02-dotnet5.md new file mode 100644 index 00000000000..57ec8bc485d --- /dev/null +++ b/csharp/change-notes/2021-03-02-dotnet5.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* The extractor has been updated to use dotnet 5 dependencies. diff --git a/csharp/extractor/Semmle.Extraction.CIL.Driver/Semmle.Extraction.CIL.Driver.csproj b/csharp/extractor/Semmle.Extraction.CIL.Driver/Semmle.Extraction.CIL.Driver.csproj index 67e40dae2d8..dea12d5d012 100644 --- a/csharp/extractor/Semmle.Extraction.CIL.Driver/Semmle.Extraction.CIL.Driver.csproj +++ b/csharp/extractor/Semmle.Extraction.CIL.Driver/Semmle.Extraction.CIL.Driver.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 Semmle.Extraction.CIL.Driver Semmle.Extraction.CIL.Driver false diff --git a/csharp/extractor/Semmle.Extraction.CIL/Context.Factories.cs b/csharp/extractor/Semmle.Extraction.CIL/Context.Factories.cs index 65c72487b65..7cdfa949390 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Context.Factories.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Context.Factories.cs @@ -128,6 +128,11 @@ namespace Semmle.Extraction.CIL case HandleKind.TypeDefinition: entity = new TypeDefinitionType(this, (TypeDefinitionHandle)handle); break; + case HandleKind.StandaloneSignature: + var signature = MdReader.GetStandaloneSignature((StandaloneSignatureHandle)handle); + var method = signature.DecodeMethodSignature(gc.Cx.TypeSignatureDecoder, gc); + entity = new FunctionPointerType(this, method); + break; default: throw new InternalError("Unhandled handle kind " + handle.Kind); } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs index 9007e0b8b90..184e37a1adf 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs @@ -56,7 +56,8 @@ namespace Semmle.Extraction.CIL.Entities private static readonly Dictionary wellKnownEnums = new Dictionary { { "System.AttributeTargets", PrimitiveTypeCode.Int32 }, - { "System.ComponentModel.EditorBrowsableState", PrimitiveTypeCode.Int32 } + { "System.ComponentModel.EditorBrowsableState", PrimitiveTypeCode.Int32 }, + { "System.Diagnostics.DebuggerBrowsableState", PrimitiveTypeCode.Int32 } }; } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Instruction.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Instruction.cs index 9cfcf444e66..3ea9332644c 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Instruction.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Instruction.cs @@ -385,19 +385,21 @@ namespace Semmle.Extraction.CIL.Entities case Payload.Type: case Payload.Field: case Payload.ValueType: - // A generic EntityHandle. - var handle = MetadataTokens.EntityHandle(payloadValue); - var target = Cx.CreateGeneric(Method, handle); - yield return target; - if (target != null) { - yield return Tuples.cil_access(this, target); + // A generic EntityHandle. + var handle = MetadataTokens.EntityHandle(payloadValue); + var target = Cx.CreateGeneric(Method, handle); + yield return target; + if (target != null) + { + yield return Tuples.cil_access(this, target); + } + else + { + throw new InternalError($"Unable to create payload type {PayloadType} for opcode {OpCode}"); + } + break; } - else - { - throw new InternalError($"Unable to create payload type {PayloadType} for opcode {OpCode}"); - } - break; case Payload.Arg8: case Payload.Arg16: if (Method.Parameters is object) @@ -417,10 +419,33 @@ namespace Semmle.Extraction.CIL.Entities case Payload.Target32: case Payload.Switch: case Payload.Ignore8: - case Payload.CallSiteDesc: // These are not handled here. // Some of these are handled by JumpContents(). break; + case Payload.CallSiteDesc: + { + var handle = MetadataTokens.EntityHandle(payloadValue); + IExtractedEntity? target = null; + try + { + target = Cx.CreateGeneric(Method, handle); + } + catch (Exception exc) + { + Cx.Extractor.Logger.Log(Util.Logging.Severity.Warning, $"Couldn't interpret payload of payload type {PayloadType} as a function pointer type. {exc.Message} {exc.StackTrace}"); + } + + if (target != null) + { + yield return target; + yield return Tuples.cil_access(this, target); + } + else + { + throw new InternalError($"Unable to create payload type {PayloadType} for opcode {OpCode}"); + } + break; + } default: throw new InternalError($"Unhandled payload type {PayloadType}"); } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Semmle.Extraction.CIL.csproj b/csharp/extractor/Semmle.Extraction.CIL/Semmle.Extraction.CIL.csproj index eb90b909b81..7cae08acc48 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Semmle.Extraction.CIL.csproj +++ b/csharp/extractor/Semmle.Extraction.CIL/Semmle.Extraction.CIL.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + net5.0 Semmle.Extraction.CIL Semmle.Extraction.CIL false diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Driver/Semmle.Extraction.CSharp.Driver.csproj b/csharp/extractor/Semmle.Extraction.CSharp.Driver/Semmle.Extraction.CSharp.Driver.csproj index 3ec25c498fe..7ae23fdcd2e 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Driver/Semmle.Extraction.CSharp.Driver.csproj +++ b/csharp/extractor/Semmle.Extraction.CSharp.Driver/Semmle.Extraction.CSharp.Driver.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 Semmle.Extraction.CSharp.Driver Semmle.Extraction.CSharp.Driver false diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs index dfbe8df2f06..dc775835e70 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs @@ -88,6 +88,11 @@ namespace Semmle.BuildAnalyser var projDir = fileName.Directory; var root = projFile.DocumentElement; + if (root is null) + { + throw new NotSupportedException("Project file without root is not supported."); + } + // Figure out if it's dotnet core var netCoreProjectFile = root.GetAttribute("Sdk") == "Microsoft.NET.Sdk"; @@ -96,34 +101,52 @@ namespace Semmle.BuildAnalyser { var explicitCsFiles = root .SelectNodes("/Project/ItemGroup/Compile/@Include", mgr) - .NodeList() + ?.NodeList() .Select(node => node.Value) - .Select(cs => Path.DirectorySeparatorChar == '/' ? cs.Replace("\\", "/") : cs) - .Select(f => Path.GetFullPath(Path.Combine(projDir.FullName, f))); + .Select(cs => GetFullPath(cs, projDir)) + .Where(s => s is not null) + ?? Enumerable.Empty(); var additionalCsFiles = System.IO.Directory.GetFiles(directoryName, "*.cs", SearchOption.AllDirectories); +#nullable disable warnings return (explicitCsFiles.Concat(additionalCsFiles).ToArray(), Array.Empty()); +#nullable restore warnings } var references = root .SelectNodes("/msbuild:Project/msbuild:ItemGroup/msbuild:Reference/@Include", mgr) - .NodeList() + ?.NodeList() .Select(node => node.Value) - .ToArray(); + .Where(s => s is not null) + .ToArray() + ?? Array.Empty(); var relativeCsIncludes = root .SelectNodes("/msbuild:Project/msbuild:ItemGroup/msbuild:Compile/@Include", mgr) - .NodeList() + ?.NodeList() .Select(node => node.Value) - .ToArray(); + .ToArray() + ?? Array.Empty(); var csFiles = relativeCsIncludes - .Select(cs => Path.DirectorySeparatorChar == '/' ? cs.Replace("\\", "/") : cs) - .Select(f => Path.GetFullPath(Path.Combine(projDir.FullName, f))) + .Select(cs => GetFullPath(cs, projDir)) + .Where(s => s is not null) .ToArray(); +#nullable disable warnings return (csFiles, references); +#nullable restore warnings + } + + private static string? GetFullPath(string? file, DirectoryInfo? projDir) + { + if (file is null) + { + return null; + } + + return Path.GetFullPath(Path.Combine(projDir?.FullName ?? string.Empty, Path.DirectorySeparatorChar == '/' ? file.Replace("\\", "/") : file)); } private readonly string[] references; diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs index e29b1b4ac1e..94e65d61462 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs @@ -113,6 +113,12 @@ namespace Semmle.BuildAnalyser { using var p = Process.Start(pi); + if (p is null) + { + pm.FailedNugetCommand(pi.FileName, pi.Arguments, "Couldn't start process."); + return; + } + var output = p.StandardOutput.ReadToEnd(); var error = p.StandardError.ReadToEnd(); diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj index 277310cc341..adf51941ad7 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 Semmle.Extraction.CSharp.Standalone Semmle.Extraction.CSharp.Standalone false diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Name.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Name.cs index faf5c9e2bd1..ed875a5e836 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Name.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Name.cs @@ -13,6 +13,13 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions var target = symbolInfo.Symbol; + if (target == null && + symbolInfo.CandidateReason == CandidateReason.OverloadResolutionFailure && + info.Node.Parent.IsKind(SyntaxKind.SuppressNullableWarningExpression)) + { + target = symbolInfo.CandidateSymbols.FirstOrDefault(); + } + if (target == null && symbolInfo.CandidateReason == CandidateReason.OverloadResolutionFailure) { // The expression is probably a cast diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Semmle.Extraction.CSharp.csproj b/csharp/extractor/Semmle.Extraction.CSharp/Semmle.Extraction.CSharp.csproj index fab4da0605b..d3c46c4a714 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Semmle.Extraction.CSharp.csproj +++ b/csharp/extractor/Semmle.Extraction.CSharp/Semmle.Extraction.CSharp.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net5.0 Semmle.Extraction.CSharp Semmle.Extraction.CSharp false diff --git a/csharp/extractor/Semmle.Extraction.Tests/Semmle.Extraction.Tests.csproj b/csharp/extractor/Semmle.Extraction.Tests/Semmle.Extraction.Tests.csproj index 830529d3710..5b242d984ee 100644 --- a/csharp/extractor/Semmle.Extraction.Tests/Semmle.Extraction.Tests.csproj +++ b/csharp/extractor/Semmle.Extraction.Tests/Semmle.Extraction.Tests.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 false win-x64;linux-x64;osx-x64 enable diff --git a/csharp/extractor/Semmle.Extraction/Semmle.Extraction.csproj b/csharp/extractor/Semmle.Extraction/Semmle.Extraction.csproj index 37df9b4dcda..795e8c2d45d 100644 --- a/csharp/extractor/Semmle.Extraction/Semmle.Extraction.csproj +++ b/csharp/extractor/Semmle.Extraction/Semmle.Extraction.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + net5.0 Semmle.Extraction Semmle.Extraction false diff --git a/csharp/extractor/Semmle.Extraction/TrapWriter.cs b/csharp/extractor/Semmle.Extraction/TrapWriter.cs index e1004e66cc7..10ebd7a56cc 100644 --- a/csharp/extractor/Semmle.Extraction/TrapWriter.cs +++ b/csharp/extractor/Semmle.Extraction/TrapWriter.cs @@ -247,7 +247,13 @@ namespace Semmle.Extraction } try { - Directory.CreateDirectory(Path.GetDirectoryName(nested)); + var directoryName = Path.GetDirectoryName(nested); + if (directoryName is null) + { + logger.Log(Severity.Warning, "Failed to get directory name from path '" + nested + "'."); + throw new InvalidOperationException(); + } + Directory.CreateDirectory(directoryName); } catch (PathTooLongException) { diff --git a/csharp/extractor/Semmle.Util.Tests/LongPaths.cs b/csharp/extractor/Semmle.Util.Tests/LongPaths.cs index 44b047b6d8d..d65dd9e6a50 100644 --- a/csharp/extractor/Semmle.Util.Tests/LongPaths.cs +++ b/csharp/extractor/Semmle.Util.Tests/LongPaths.cs @@ -72,7 +72,7 @@ namespace SemmleTests.Semmle.Util public void Move() { File.WriteAllText(shortPath, "abc"); - Directory.CreateDirectory(Path.GetDirectoryName(longPath)); + Directory.CreateDirectory(Path.GetDirectoryName(longPath)!); File.Delete(longPath); File.Move(shortPath, longPath); File.Move(longPath, shortPath); @@ -84,7 +84,7 @@ namespace SemmleTests.Semmle.Util { File.WriteAllText(shortPath, "abc"); File.Delete(longPath); - Directory.CreateDirectory(Path.GetDirectoryName(longPath)); + Directory.CreateDirectory(Path.GetDirectoryName(longPath)!); File.Move(shortPath, longPath); File.WriteAllText(shortPath, "def"); FileUtils.MoveOrReplace(shortPath, longPath); @@ -117,7 +117,7 @@ namespace SemmleTests.Semmle.Util { var buffer2 = new byte[10]; - Directory.CreateDirectory(Path.GetDirectoryName(longPath)); + Directory.CreateDirectory(Path.GetDirectoryName(longPath)!); using (var s3 = new FileStream(longPath, FileMode.Create, FileAccess.Write, FileShare.None)) { diff --git a/csharp/extractor/Semmle.Util.Tests/Semmle.Util.Tests.csproj b/csharp/extractor/Semmle.Util.Tests/Semmle.Util.Tests.csproj index 3acf1a1fa42..ca9599cf770 100644 --- a/csharp/extractor/Semmle.Util.Tests/Semmle.Util.Tests.csproj +++ b/csharp/extractor/Semmle.Util.Tests/Semmle.Util.Tests.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 false win-x64;linux-x64;osx-x64 enable diff --git a/csharp/extractor/Semmle.Util/FileUtils.cs b/csharp/extractor/Semmle.Util/FileUtils.cs index 89e35055fee..aa655a6e674 100644 --- a/csharp/extractor/Semmle.Util/FileUtils.cs +++ b/csharp/extractor/Semmle.Util/FileUtils.cs @@ -33,10 +33,7 @@ namespace Semmle.Util /// Target file. public static void MoveOrReplace(string src, string dest) { - // Potential race condition here. - // .net offers the facility to either move a file, or to replace it. - File.Delete(dest); - File.Move(src, dest); + File.Move(src, dest, overwrite: true); } /// diff --git a/csharp/extractor/Semmle.Util/ProcessStartInfoExtensions.cs b/csharp/extractor/Semmle.Util/ProcessStartInfoExtensions.cs index 998b6909e10..3519080ab76 100644 --- a/csharp/extractor/Semmle.Util/ProcessStartInfoExtensions.cs +++ b/csharp/extractor/Semmle.Util/ProcessStartInfoExtensions.cs @@ -13,6 +13,12 @@ namespace Semmle.Util { stdout = new List(); using var process = Process.Start(pi); + + if (process is null) + { + return -1; + } + string? s; do { diff --git a/csharp/extractor/Semmle.Util/Semmle.Util.csproj b/csharp/extractor/Semmle.Util/Semmle.Util.csproj index fdcd0672395..63ac78cb7cc 100644 --- a/csharp/extractor/Semmle.Util/Semmle.Util.csproj +++ b/csharp/extractor/Semmle.Util/Semmle.Util.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net5.0 Semmle.Util Semmle.Util false diff --git a/csharp/ql/src/experimental/ir/implementation/internal/TOperand.qll b/csharp/ql/src/experimental/ir/implementation/internal/TOperand.qll new file mode 100644 index 00000000000..9c3e7620186 --- /dev/null +++ b/csharp/ql/src/experimental/ir/implementation/internal/TOperand.qll @@ -0,0 +1,130 @@ +private import TInstruction +private import OperandTag +private import experimental.ir.implementation.raw.internal.IRConstruction as RawConstruction +private import experimental.ir.implementation.unaliased_ssa.internal.SSAConstruction as UnaliasedConstruction +private import experimental.ir.implementation.raw.IR as Raw +private import experimental.ir.implementation.unaliased_ssa.IR as Unaliased +private import experimental.ir.internal.Overlap + +/** + * Provides the newtype used to represent operands across all phases of the IR. + */ +private module Internal { + /** + * An IR operand. `TOperand` is shared across all phases of the IR. There are branches of this + * type for operands created directly from the AST (`TRegisterOperand` and `TNonSSAMemoryOperand`), + * for operands computed by each stage of SSA construction (`T*PhiOperand` and + * `TAliasedChiOperand`), and a placehold branch for operands that do not exist in a given + * stage of IR construction (`TNoOperand`). + */ + cached + newtype TOperand = + // RAW + TRegisterOperand(TRawInstruction useInstr, RegisterOperandTag tag, TRawInstruction defInstr) { + defInstr = RawConstruction::getRegisterOperandDefinition(useInstr, tag) and + not RawConstruction::isInCycle(useInstr) and + strictcount(RawConstruction::getRegisterOperandDefinition(useInstr, tag)) = 1 + } or + // Placeholder for Phi and Chi operands in stages that don't have the corresponding instructions + TNoOperand() { none() } or + // Can be "removed" later when there's unreachable code + // These operands can be reused across all three stages. They just get different defs. + TNonSSAMemoryOperand(Raw::Instruction useInstr, MemoryOperandTag tag) { + // Has no definition in raw but will get definitions later + useInstr.getOpcode().hasOperand(tag) + } or + TUnaliasedPhiOperand( + Unaliased::PhiInstruction useInstr, Unaliased::Instruction defInstr, + Unaliased::IRBlock predecessorBlock, Overlap overlap + ) { + defInstr = UnaliasedConstruction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap) + } +} + +/** + * Reexports some branches from `TOperand` so they can be used in stage modules without importing + * `TOperand` itself. + */ +private module Shared { + class TRegisterOperand = Internal::TRegisterOperand; + + /** + * Returns the register operand with the specified parameters. + */ + TRegisterOperand registerOperand( + TRawInstruction useInstr, RegisterOperandTag tag, TRawInstruction defInstr + ) { + result = Internal::TRegisterOperand(useInstr, tag, defInstr) + } + + class TNonSSAMemoryOperand = Internal::TNonSSAMemoryOperand; + + /** + * Returns the non-Phi memory operand with the specified parameters. + */ + TNonSSAMemoryOperand nonSSAMemoryOperand(TRawInstruction useInstr, MemoryOperandTag tag) { + result = Internal::TNonSSAMemoryOperand(useInstr, tag) + } +} + +/** + * Provides wrappers for the constructors of each branch of `TOperand` that is used by the + * raw IR stage. + * These wrappers are not parameterized because it is not possible to invoke an IPA constructor via + * a class alias. + */ +module RawOperands { + import Shared + + class TPhiOperand = Internal::TNoOperand; + + class TChiOperand = Internal::TNoOperand; + + class TNonPhiMemoryOperand = TNonSSAMemoryOperand or TChiOperand; + + /** + * Returns the Phi operand with the specified parameters. + */ + TPhiOperand phiOperand( + Raw::PhiInstruction useInstr, Raw::Instruction defInstr, Raw::IRBlock predecessorBlock, + Overlap overlap + ) { + none() + } + + /** + * Returns the Chi operand with the specified parameters. + */ + TChiOperand chiOperand(Raw::Instruction useInstr, ChiOperandTag tag) { none() } +} + +/** + * Provides wrappers for the constructors of each branch of `TOperand` that is used by the + * unaliased SSA stage. + * These wrappers are not parameterized because it is not possible to invoke an IPA constructor via + * a class alias. + */ +module UnaliasedSSAOperands { + import Shared + + class TPhiOperand = Internal::TUnaliasedPhiOperand; + + class TChiOperand = Internal::TNoOperand; + + class TNonPhiMemoryOperand = TNonSSAMemoryOperand or TChiOperand; + + /** + * Returns the Phi operand with the specified parameters. + */ + TPhiOperand phiOperand( + Unaliased::PhiInstruction useInstr, Unaliased::Instruction defInstr, + Unaliased::IRBlock predecessorBlock, Overlap overlap + ) { + result = Internal::TUnaliasedPhiOperand(useInstr, defInstr, predecessorBlock, overlap) + } + + /** + * Returns the Chi operand with the specified parameters. + */ + TChiOperand chiOperand(Unaliased::Instruction useInstr, ChiOperandTag tag) { none() } +} diff --git a/csharp/ql/src/experimental/ir/implementation/raw/Operand.qll b/csharp/ql/src/experimental/ir/implementation/raw/Operand.qll index a12e35d471b..a2ce0662dc2 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/Operand.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/Operand.qll @@ -10,79 +10,32 @@ private import Imports::MemoryAccessKind private import Imports::IRType private import Imports::Overlap private import Imports::OperandTag - -cached -private newtype TOperand = - TRegisterOperand(Instruction useInstr, RegisterOperandTag tag, Instruction defInstr) { - defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and - not Construction::isInCycle(useInstr) and - strictcount(Construction::getRegisterOperandDefinition(useInstr, tag)) = 1 - } or - TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) { - useInstr.getOpcode().hasOperand(tag) - } or - TPhiOperand( - PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap - ) { - defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap) - } +private import Imports::TOperand +private import internal.OperandInternal /** - * Base class for all register operands. This is a placeholder for the IPA union type that we will - * eventually use for this purpose. + * An operand of an `Instruction` in this stage of the IR. Implemented as a union of the branches + * of `TOperand` that are used in this stage. */ -private class RegisterOperandBase extends TRegisterOperand { - /** Gets a textual representation of this element. */ - abstract string toString(); -} - -/** - * Returns the register operand with the specified parameters. - */ -private RegisterOperandBase registerOperand( - Instruction useInstr, RegisterOperandTag tag, Instruction defInstr -) { - result = TRegisterOperand(useInstr, tag, defInstr) -} - -/** - * Base class for all non-Phi memory operands. This is a placeholder for the IPA union type that we - * will eventually use for this purpose. - */ -private class NonPhiMemoryOperandBase extends TNonPhiMemoryOperand { - /** Gets a textual representation of this element. */ - abstract string toString(); -} - -/** - * Returns the non-Phi memory operand with the specified parameters. - */ -private NonPhiMemoryOperandBase nonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) { - result = TNonPhiMemoryOperand(useInstr, tag) -} - -/** - * Base class for all Phi operands. This is a placeholder for the IPA union type that we will - * eventually use for this purpose. - */ -private class PhiOperandBase extends TPhiOperand { - abstract string toString(); -} - -/** - * Returns the Phi operand with the specified parameters. - */ -private PhiOperandBase phiOperand( - Instruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap -) { - result = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) -} +private class TStageOperand = + TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand; /** * An operand of an `Instruction`. The operand represents a use of the result of one instruction * (the defining instruction) in another instruction (the use instruction) */ -class Operand extends TOperand { +class Operand extends TStageOperand { + cached + Operand() { + // Ensure that the operand does not refer to instructions from earlier stages that are unreachable here + exists(Instruction use, Instruction def | this = registerOperand(use, _, def)) or + exists(Instruction use | this = nonSSAMemoryOperand(use, _)) or + exists(Instruction use, Instruction def, IRBlock predecessorBlock | + this = phiOperand(use, def, predecessorBlock, _) + ) or + exists(Instruction use | this = chiOperand(use, _)) + } + /** Gets a textual representation of this element. */ string toString() { result = "Operand" } @@ -238,9 +191,11 @@ class Operand extends TOperand { * An operand that consumes a memory result (e.g. the `LoadOperand` on a `Load` instruction). */ class MemoryOperand extends Operand { + cached MemoryOperand() { - this instanceof NonPhiMemoryOperandBase or - this instanceof PhiOperandBase + this instanceof TNonSSAMemoryOperand or + this instanceof TPhiOperand or + this instanceof TChiOperand } /** @@ -278,7 +233,8 @@ class NonPhiOperand extends Operand { NonPhiOperand() { this = registerOperand(useInstr, tag, _) or - this = nonPhiMemoryOperand(useInstr, tag) + this = nonSSAMemoryOperand(useInstr, tag) or + this = chiOperand(useInstr, tag) } final override Instruction getUse() { result = useInstr } @@ -298,10 +254,11 @@ class NonPhiOperand extends Operand { /** * An operand that consumes a register (non-memory) result. */ -class RegisterOperand extends NonPhiOperand, RegisterOperandBase { +class RegisterOperand extends NonPhiOperand, TRegisterOperand { override RegisterOperandTag tag; Instruction defInstr; + cached RegisterOperand() { this = registerOperand(useInstr, tag, defInstr) } final override string toString() { result = tag.toString() } @@ -317,10 +274,15 @@ class RegisterOperand extends NonPhiOperand, RegisterOperandBase { /** * A memory operand other than the operand of a `Phi` instruction. */ -class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase { +class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand { override MemoryOperandTag tag; - NonPhiMemoryOperand() { this = nonPhiMemoryOperand(useInstr, tag) } + cached + NonPhiMemoryOperand() { + this = nonSSAMemoryOperand(useInstr, tag) + or + this = chiOperand(useInstr, tag) + } final override string toString() { result = tag.toString() } @@ -462,12 +424,13 @@ class SideEffectOperand extends TypedOperand { /** * An operand of a `PhiInstruction`. */ -class PhiInputOperand extends MemoryOperand, PhiOperandBase { +class PhiInputOperand extends MemoryOperand, TPhiOperand { PhiInstruction useInstr; Instruction defInstr; IRBlock predecessorBlock; Overlap overlap; + cached PhiInputOperand() { this = phiOperand(useInstr, defInstr, predecessorBlock, overlap) } override string toString() { result = "Phi" } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/OperandImports.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/OperandImports.qll index 40af4631927..65676caf724 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/OperandImports.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/OperandImports.qll @@ -2,3 +2,4 @@ import experimental.ir.implementation.MemoryAccessKind as MemoryAccessKind import experimental.ir.implementation.IRType as IRType import experimental.ir.internal.Overlap as Overlap import experimental.ir.implementation.internal.OperandTag as OperandTag +import experimental.ir.implementation.internal.TOperand as TOperand diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/OperandInternal.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/OperandInternal.qll new file mode 100644 index 00000000000..771aeb9033c --- /dev/null +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/OperandInternal.qll @@ -0,0 +1,2 @@ +private import experimental.ir.implementation.internal.TOperand +import RawOperands diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll index a12e35d471b..a2ce0662dc2 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll @@ -10,79 +10,32 @@ private import Imports::MemoryAccessKind private import Imports::IRType private import Imports::Overlap private import Imports::OperandTag - -cached -private newtype TOperand = - TRegisterOperand(Instruction useInstr, RegisterOperandTag tag, Instruction defInstr) { - defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and - not Construction::isInCycle(useInstr) and - strictcount(Construction::getRegisterOperandDefinition(useInstr, tag)) = 1 - } or - TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) { - useInstr.getOpcode().hasOperand(tag) - } or - TPhiOperand( - PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap - ) { - defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap) - } +private import Imports::TOperand +private import internal.OperandInternal /** - * Base class for all register operands. This is a placeholder for the IPA union type that we will - * eventually use for this purpose. + * An operand of an `Instruction` in this stage of the IR. Implemented as a union of the branches + * of `TOperand` that are used in this stage. */ -private class RegisterOperandBase extends TRegisterOperand { - /** Gets a textual representation of this element. */ - abstract string toString(); -} - -/** - * Returns the register operand with the specified parameters. - */ -private RegisterOperandBase registerOperand( - Instruction useInstr, RegisterOperandTag tag, Instruction defInstr -) { - result = TRegisterOperand(useInstr, tag, defInstr) -} - -/** - * Base class for all non-Phi memory operands. This is a placeholder for the IPA union type that we - * will eventually use for this purpose. - */ -private class NonPhiMemoryOperandBase extends TNonPhiMemoryOperand { - /** Gets a textual representation of this element. */ - abstract string toString(); -} - -/** - * Returns the non-Phi memory operand with the specified parameters. - */ -private NonPhiMemoryOperandBase nonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) { - result = TNonPhiMemoryOperand(useInstr, tag) -} - -/** - * Base class for all Phi operands. This is a placeholder for the IPA union type that we will - * eventually use for this purpose. - */ -private class PhiOperandBase extends TPhiOperand { - abstract string toString(); -} - -/** - * Returns the Phi operand with the specified parameters. - */ -private PhiOperandBase phiOperand( - Instruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap -) { - result = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) -} +private class TStageOperand = + TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand; /** * An operand of an `Instruction`. The operand represents a use of the result of one instruction * (the defining instruction) in another instruction (the use instruction) */ -class Operand extends TOperand { +class Operand extends TStageOperand { + cached + Operand() { + // Ensure that the operand does not refer to instructions from earlier stages that are unreachable here + exists(Instruction use, Instruction def | this = registerOperand(use, _, def)) or + exists(Instruction use | this = nonSSAMemoryOperand(use, _)) or + exists(Instruction use, Instruction def, IRBlock predecessorBlock | + this = phiOperand(use, def, predecessorBlock, _) + ) or + exists(Instruction use | this = chiOperand(use, _)) + } + /** Gets a textual representation of this element. */ string toString() { result = "Operand" } @@ -238,9 +191,11 @@ class Operand extends TOperand { * An operand that consumes a memory result (e.g. the `LoadOperand` on a `Load` instruction). */ class MemoryOperand extends Operand { + cached MemoryOperand() { - this instanceof NonPhiMemoryOperandBase or - this instanceof PhiOperandBase + this instanceof TNonSSAMemoryOperand or + this instanceof TPhiOperand or + this instanceof TChiOperand } /** @@ -278,7 +233,8 @@ class NonPhiOperand extends Operand { NonPhiOperand() { this = registerOperand(useInstr, tag, _) or - this = nonPhiMemoryOperand(useInstr, tag) + this = nonSSAMemoryOperand(useInstr, tag) or + this = chiOperand(useInstr, tag) } final override Instruction getUse() { result = useInstr } @@ -298,10 +254,11 @@ class NonPhiOperand extends Operand { /** * An operand that consumes a register (non-memory) result. */ -class RegisterOperand extends NonPhiOperand, RegisterOperandBase { +class RegisterOperand extends NonPhiOperand, TRegisterOperand { override RegisterOperandTag tag; Instruction defInstr; + cached RegisterOperand() { this = registerOperand(useInstr, tag, defInstr) } final override string toString() { result = tag.toString() } @@ -317,10 +274,15 @@ class RegisterOperand extends NonPhiOperand, RegisterOperandBase { /** * A memory operand other than the operand of a `Phi` instruction. */ -class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase { +class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand { override MemoryOperandTag tag; - NonPhiMemoryOperand() { this = nonPhiMemoryOperand(useInstr, tag) } + cached + NonPhiMemoryOperand() { + this = nonSSAMemoryOperand(useInstr, tag) + or + this = chiOperand(useInstr, tag) + } final override string toString() { result = tag.toString() } @@ -462,12 +424,13 @@ class SideEffectOperand extends TypedOperand { /** * An operand of a `PhiInstruction`. */ -class PhiInputOperand extends MemoryOperand, PhiOperandBase { +class PhiInputOperand extends MemoryOperand, TPhiOperand { PhiInstruction useInstr; Instruction defInstr; IRBlock predecessorBlock; Overlap overlap; + cached PhiInputOperand() { this = phiOperand(useInstr, defInstr, predecessorBlock, overlap) } override string toString() { result = "Phi" } diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/OperandImports.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/OperandImports.qll index 40af4631927..65676caf724 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/OperandImports.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/OperandImports.qll @@ -2,3 +2,4 @@ import experimental.ir.implementation.MemoryAccessKind as MemoryAccessKind import experimental.ir.implementation.IRType as IRType import experimental.ir.internal.Overlap as Overlap import experimental.ir.implementation.internal.OperandTag as OperandTag +import experimental.ir.implementation.internal.TOperand as TOperand diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/OperandInternal.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/OperandInternal.qll new file mode 100644 index 00000000000..88a4e6f8551 --- /dev/null +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/OperandInternal.qll @@ -0,0 +1,2 @@ +private import experimental.ir.implementation.internal.TOperand +import UnaliasedSSAOperands diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index 8e904ee6bc4..a1c970121d2 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -6,6 +6,7 @@ private import Imports::Overlap private import Imports::TInstruction private import Imports::RawIR as RawIR private import SSAInstructions +private import SSAOperands private import NewIR private class OldBlock = Reachability::ReachableBlock; diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstructionInternal.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstructionInternal.qll index 15eaf8045a7..8f726b81345 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstructionInternal.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstructionInternal.qll @@ -6,3 +6,4 @@ import experimental.ir.implementation.raw.internal.IRConstruction as RawStage import experimental.ir.implementation.internal.TInstruction::UnaliasedSSAInstructions as SSAInstructions import experimental.ir.internal.IRCSharpLanguage as Language import SimpleSSA as Alias +import experimental.ir.implementation.internal.TOperand::UnaliasedSSAOperands as SSAOperands diff --git a/csharp/ql/src/semmle/code/cil/ConsistencyChecks.qll b/csharp/ql/src/semmle/code/cil/ConsistencyChecks.qll index bd6a1bc8885..51b74b2463d 100644 --- a/csharp/ql/src/semmle/code/cil/ConsistencyChecks.qll +++ b/csharp/ql/src/semmle/code/cil/ConsistencyChecks.qll @@ -79,7 +79,13 @@ class MissingValue extends InstructionViolation { * A call that does not have exactly one `getTarget()`. */ class MissingCallTarget extends InstructionViolation { - MissingCallTarget() { exists(Call c | c = instruction | count(c.getTarget()) != 1) } + MissingCallTarget() { + exists(Call c | c = instruction | + count(c.getTarget()) != 1 and not c instanceof Opcodes::Calli + or + count(c.(Opcodes::Calli).getTargetType()) != 1 and c instanceof Opcodes::Calli + ) + } override string getMessage() { result = "Call has invalid target" } } diff --git a/csharp/ql/src/semmle/code/cil/Instructions.qll b/csharp/ql/src/semmle/code/cil/Instructions.qll index bc79e15d4e4..e385ceced31 100644 --- a/csharp/ql/src/semmle/code/cil/Instructions.qll +++ b/csharp/ql/src/semmle/code/cil/Instructions.qll @@ -482,6 +482,22 @@ module Opcodes { override string getOpcodeName() { result = "call" } } + /** A `calli` instruction. */ + class Calli extends Call, @cil_calli { + override string getOpcodeName() { result = "calli" } + + override Callable getTarget() { none() } + + /** Gets the function pointer type targetted by this instruction. */ + FunctionPointerType getTargetType() { cil_access(this, result) } + + // The number of items popped/pushed from the stack depends on the target of + // the call. Also, we need to pop the function pointer itself too. + override int getPopCount() { result = getTargetType().getCallPopCount() + 1 } + + override int getPushCount() { result = getTargetType().getCallPushCount() } + } + /** A `callvirt` instruction. */ class Callvirt extends Call, @cil_callvirt { override string getOpcodeName() { result = "callvirt" } diff --git a/csharp/ql/src/semmle/code/cil/Types.qll b/csharp/ql/src/semmle/code/cil/Types.qll index 1bc74767d6b..16ea219e8ac 100644 --- a/csharp/ql/src/semmle/code/cil/Types.qll +++ b/csharp/ql/src/semmle/code/cil/Types.qll @@ -310,4 +310,15 @@ class FunctionPointerType extends Type, CustomModifierReceiver, Parameterizable, int getCallingConvention() { cil_function_pointer_calling_conventions(this, result) } override string toString() { result = Type.super.toString() } + + /** Holds if the return type is `void`. */ + predicate returnsVoid() { getReturnType() instanceof VoidType } + + /** Gets the number of stack items pushed in a call to this method. */ + int getCallPushCount() { if returnsVoid() then result = 0 else result = 1 } + + /** Gets the number of stack items popped in a call to this method. */ + int getCallPopCount() { result = count(getRawParameter(_)) } + + override string getLabel() { result = getName() } } diff --git a/csharp/ql/src/semmle/code/csharp/Type.qll b/csharp/ql/src/semmle/code/csharp/Type.qll index 13b7f8275df..cf055062e33 100644 --- a/csharp/ql/src/semmle/code/csharp/Type.qll +++ b/csharp/ql/src/semmle/code/csharp/Type.qll @@ -902,6 +902,8 @@ class FunctionPointerType extends Type, Parameterizable, @function_pointer_type AnnotatedType getAnnotatedReturnType() { result.appliesTo(this) } override string getAPrimaryQlClass() { result = "FunctionPointerType" } + + override string getLabel() { result = getName() } } /** diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll b/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll index 396fb52a85d..bdcfa6ac4b7 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll @@ -995,7 +995,7 @@ module Internal { // pre-SSA predicates private module PreCFG { private import semmle.code.csharp.controlflow.internal.PreBasicBlocks as PreBasicBlocks - private import semmle.code.csharp.controlflow.internal.PreSsa as PreSsa + private import semmle.code.csharp.controlflow.internal.PreSsa /** * Holds if pre-basic-block `bb` only is reached when guard `g` has abstract value `v`, @@ -1081,25 +1081,25 @@ module Internal { pragma[noinline] private predicate conditionalAssign0( - Guard guard, AbstractValue vGuard, PreSsa::Definition def, Expr e, PreSsa::Definition upd, + Guard guard, AbstractValue vGuard, PreSsa::PhiNode phi, Expr e, PreSsa::Definition upd, PreBasicBlocks::PreBasicBlock bbGuard ) { e = upd.getDefinition().getSource() and - upd = def.getAPhiInput() and + upd = phi.getAnInput() and preControlsDirect(guard, upd.getBasicBlock(), vGuard) and bbGuard.getAnElement() = guard and - bbGuard.strictlyDominates(def.getBasicBlock()) and - not preControlsDirect(guard, def.getBasicBlock(), vGuard) + bbGuard.strictlyDominates(phi.getBasicBlock()) and + not preControlsDirect(guard, phi.getBasicBlock(), vGuard) } pragma[noinline] private predicate conditionalAssign1( - Guard guard, AbstractValue vGuard, PreSsa::Definition def, Expr e, PreSsa::Definition upd, + Guard guard, AbstractValue vGuard, PreSsa::PhiNode phi, Expr e, PreSsa::Definition upd, PreBasicBlocks::PreBasicBlock bbGuard, PreSsa::Definition other ) { - conditionalAssign0(guard, vGuard, def, e, upd, bbGuard) and + conditionalAssign0(guard, vGuard, phi, e, upd, bbGuard) and other != upd and - other = def.getAPhiInput() + other = phi.getAnInput() } pragma[noinline] @@ -1127,7 +1127,7 @@ module Internal { ) { conditionalAssign1(guard, vGuard, def, e, upd, bbGuard, other) and other.getBasicBlock().dominates(bbGuard) and - not PreSsa::ssaDefReachesEndOfBlock(getConditionalSuccessor(guard, vGuard), other, _) + not other.isLiveAtEndOfBlock(getConditionalSuccessor(guard, vGuard)) } /** @@ -1315,14 +1315,14 @@ module Internal { */ private PreSsa::Definition getADefinition(PreSsa::Definition def, boolean fromBackEdge) { result = def and - not exists(def.getAPhiInput()) and + not def instanceof PreSsa::PhiNode and fromBackEdge = false or exists(PreSsa::Definition input, PreBasicBlocks::PreBasicBlock pred, boolean fbe | - input = def.getAPhiInput() + input = def.(PreSsa::PhiNode).getAnInput() | pred = def.getBasicBlock().getAPredecessor() and - PreSsa::ssaDefReachesEndOfBlock(pred, input, _) and + input.isLiveAtEndOfBlock(pred) and result = getADefinition(input, fbe) and (if def.getBasicBlock().dominates(pred) then fromBackEdge = true else fromBackEdge = fbe) ) @@ -1446,7 +1446,7 @@ module Internal { private predicate firstReadSameVarUniquePredecesssor( PreSsa::Definition def, AssignableRead read ) { - PreSsa::firstReadSameVar(def, read) and + read = def.getAFirstRead() and not exists(AssignableRead other | PreSsa::adjacentReadPairSameVar(other, read) | other != read ) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll index d1398719c15..31155dea0ae 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll @@ -82,13 +82,6 @@ class PreBasicBlock extends ControlFlowElement { or this.strictlyDominates(bb) } - - predicate inDominanceFrontier(PreBasicBlock df) { - this.dominatesPredecessor(df) and - not this.strictlyDominates(df) - } - - private predicate dominatesPredecessor(PreBasicBlock df) { this.dominates(df.getAPredecessor()) } } private Completion getConditionalCompletion(ConditionalCompletion cc) { diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreSsa.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreSsa.qll index 8243520aaf1..5ac313651d7 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreSsa.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreSsa.qll @@ -1,370 +1,74 @@ +import csharp + /** - * INTERNAL: Do not use. - * * Provides an SSA implementation based on "pre-basic-blocks", restricted * to local scope variables and fields/properties that behave like local * scope variables. - * - * The logic is duplicated from the implementation in `SSA.qll`, and - * being an internal class, all predicate documentation has been removed. */ +module PreSsa { + import pressa.SsaImplSpecific + private import pressa.SsaImplCommon as SsaImpl -import csharp -private import AssignableDefinitions -private import PreBasicBlocks -private import ControlFlowGraphImpl -private import semmle.code.csharp.controlflow.Guards as Guards + class Definition extends SsaImpl::Definition { + final AssignableRead getARead() { + exists(BasicBlock bb, int i | + SsaImpl::ssaDefReachesRead(_, this, bb, i) and + result = bb.getElement(i) + ) + } -pragma[noinline] -private predicate assignableNoCapturing(Assignable a, Callable c) { - exists(AssignableAccess aa | aa.getTarget() = a | c = aa.getEnclosingCallable()) and - forall(AssignableDefinition def | def.getTarget() = a | - c = def.getEnclosingCallable() - or - def.getEnclosingCallable() instanceof Constructor - ) -} + final AssignableDefinition getDefinition() { + exists(BasicBlock bb, int i, SourceVariable v | + this.definesAt(v, bb, i) and + definitionAt(result, bb, i, v) + ) + } -pragma[noinline] -private predicate assignableNoComplexQualifiers(Assignable a) { - forall(QualifiableExpr qe | qe.(AssignableAccess).getTarget() = a | qe.targetIsThisInstance()) -} + final AssignableRead getAFirstRead() { + exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 | + this.definesAt(_, bb1, i1) and + SsaImpl::adjacentDefRead(this, bb1, i1, bb2, i2) and + result = bb2.getElement(i2) + ) + } -/** - * A simple assignable. Either a local scope variable or a field/property - * that behaves like a local scope variable. - */ -class SimpleAssignable extends Assignable { - private Callable c; + private Definition getAPhiInputOrPriorDefinition() { + result = this.(PhiNode).getAnInput() or + SsaImpl::uncertainWriteDefinitionInput(this, result) + } - SimpleAssignable() { - ( - this instanceof LocalScopeVariable + final Definition getAnUltimateDefinition() { + result = this.getAPhiInputOrPriorDefinition*() and + not result instanceof PhiNode + } + + final predicate isLiveAtEndOfBlock(BasicBlock bb) { + SsaImpl::ssaDefReachesEndOfBlock(bb, this, _) + } + + Location getLocation() { + result = this.getDefinition().getLocation() or - this instanceof Field - or - this = any(TrivialProperty tp | not tp.isOverridableOrImplementable()) - ) and - assignableNoCapturing(this, c) and - assignableNoComplexQualifiers(this) + exists(Callable c, BasicBlock bb, SourceVariable v | + this.definesAt(v, bb, -1) and + implicitEntryDef(c, bb, v) and + result = c.getLocation() + ) + } } - /** Gets a callable in which this simple assignable can be analyzed. */ - Callable getACallable() { result = c } -} + class PhiNode extends SsaImpl::PhiNode, Definition { + final override Location getLocation() { result = this.getBasicBlock().getLocation() } -pragma[noinline] -private predicate phiNodeMaybeLive(PreBasicBlock bb, SimpleAssignable a) { - exists(PreBasicBlock def | defAt(def, _, _, a) | def.inDominanceFrontier(bb)) -} - -private newtype TPreSsaDef = - TExplicitPreSsaDef(PreBasicBlock bb, int i, AssignableDefinition def, SimpleAssignable a) { - assignableDefAtLive(bb, i, def, a) - } or - TImplicitEntryPreSsaDef(Callable c, PreBasicBlock bb, Assignable a) { - implicitEntryDef(c, bb, a) and - liveAtEntry(bb, a) - } or - TPhiPreSsaDef(PreBasicBlock bb, SimpleAssignable a) { - phiNodeMaybeLive(bb, a) and - liveAtEntry(bb, a) + final Definition getAnInput() { SsaImpl::phiHasInputFromBlock(this, result, _) } } -class Definition extends TPreSsaDef { - string toString() { - exists(AssignableDefinition def | this = TExplicitPreSsaDef(_, _, def, _) | - result = def.toString() - ) - or - exists(SimpleAssignable a | this = TImplicitEntryPreSsaDef(_, _, a) | - result = "implicit(" + a + ")" - ) - or - exists(SimpleAssignable a | this = TPhiPreSsaDef(_, a) | result = "phi(" + a.toString() + ")") - } - - SimpleAssignable getAssignable() { - this = TExplicitPreSsaDef(_, _, _, result) - or - this = TImplicitEntryPreSsaDef(_, _, result) - or - this = TPhiPreSsaDef(_, result) - } - - AssignableRead getARead() { - firstReadSameVar(this, result) - or - exists(AssignableRead read | firstReadSameVar(this, read) | - adjacentReadPairSameVar+(read, result) + predicate adjacentReadPairSameVar(AssignableRead read1, AssignableRead read2) { + exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 | + read1 = bb1.getElement(i1) and + variableRead(bb1, i1, _, true) and + SsaImpl::adjacentDefRead(_, bb1, i1, bb2, i2) and + read2 = bb2.getElement(i2) ) } - - Location getLocation() { - exists(AssignableDefinition def | this = TExplicitPreSsaDef(_, _, def, _) | - result = def.getLocation() - ) - or - exists(Callable c | this = TImplicitEntryPreSsaDef(c, _, _) | result = c.getLocation()) - or - exists(PreBasicBlock bb | this = TPhiPreSsaDef(bb, _) | result = bb.getLocation()) - } - - PreBasicBlock getBasicBlock() { - this = TExplicitPreSsaDef(result, _, _, _) - or - this = TImplicitEntryPreSsaDef(_, result, _) - or - this = TPhiPreSsaDef(result, _) - } - - Callable getCallable() { result = this.getBasicBlock().getEnclosingCallable() } - - AssignableDefinition getDefinition() { this = TExplicitPreSsaDef(_, _, result, _) } - - Definition getAPhiInput() { - exists(PreBasicBlock bb, PreBasicBlock phiPred, SimpleAssignable a | - this = TPhiPreSsaDef(bb, a) - | - bb.getAPredecessor() = phiPred and - ssaDefReachesEndOfBlock(phiPred, result, a) - ) - } - - Definition getAnUltimateDefinition() { - result = this.getAPhiInput*() and - not result = TPhiPreSsaDef(_, _) - } -} - -predicate implicitEntryDef(Callable c, PreBasicBlock bb, SimpleAssignable a) { - not a instanceof LocalScopeVariable and - c = a.getACallable() and - scopeFirst(c, bb) -} - -private predicate assignableDefAt( - PreBasicBlock bb, int i, AssignableDefinition def, SimpleAssignable a -) { - bb.getElement(i) = def.getExpr() and - a = def.getTarget() and - // In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x` - not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | first = def | - second.getAssignment() = first.getAssignment() and - second.getEvaluationOrder() > first.getEvaluationOrder() and - second.getTarget() = a - ) - or - def.(ImplicitParameterDefinition).getParameter() = a and - exists(Callable c | a = c.getAParameter() | - scopeFirst(c, bb) and - i = -1 - ) -} - -private predicate readAt(PreBasicBlock bb, int i, AssignableRead read, SimpleAssignable a) { - read = bb.getElement(i) and - read.getTarget() = a -} - -pragma[noinline] -private predicate exitBlock(PreBasicBlock bb, Callable c) { - scopeLast(c, bb.getLastElement(), _) and - c = bb.getEnclosingCallable() -} - -private predicate outRefExitRead(PreBasicBlock bb, int i, LocalScopeVariable v) { - exitBlock(bb, v.getCallable()) and - i = bb.length() + 1 and - (v.isRef() or v.(Parameter).isOut()) -} - -private newtype RefKind = - Read() or - Write(boolean certain) { certain = true or certain = false } - -private predicate ref(PreBasicBlock bb, int i, SimpleAssignable a, RefKind k) { - (readAt(bb, i, _, a) or outRefExitRead(bb, i, a)) and - k = Read() - or - exists(AssignableDefinition def, boolean certain | assignableDefAt(bb, i, def, a) | - (if def.getTargetAccess().isRefArgument() then certain = false else certain = true) and - k = Write(certain) - ) -} - -private int refRank(PreBasicBlock bb, int i, SimpleAssignable a, RefKind k) { - i = rank[result](int j | ref(bb, j, a, _)) and - ref(bb, i, a, k) -} - -private int maxRefRank(PreBasicBlock bb, SimpleAssignable a) { - result = refRank(bb, _, a, _) and - not result + 1 = refRank(bb, _, a, _) -} - -private int firstReadOrCertainWrite(PreBasicBlock bb, SimpleAssignable a) { - result = - min(int r, RefKind k | - r = refRank(bb, _, a, k) and - k != Write(false) - | - r - ) -} - -predicate liveAtEntry(PreBasicBlock bb, SimpleAssignable a) { - refRank(bb, _, a, Read()) = firstReadOrCertainWrite(bb, a) - or - not exists(firstReadOrCertainWrite(bb, a)) and - liveAtExit(bb, a) -} - -private predicate liveAtExit(PreBasicBlock bb, SimpleAssignable a) { - liveAtEntry(bb.getASuccessor(), a) -} - -predicate assignableDefAtLive(PreBasicBlock bb, int i, AssignableDefinition def, SimpleAssignable a) { - assignableDefAt(bb, i, def, a) and - exists(int rnk | rnk = refRank(bb, i, a, Write(_)) | - rnk + 1 = refRank(bb, _, a, Read()) - or - rnk = maxRefRank(bb, a) and - liveAtExit(bb, a) - ) -} - -predicate defAt(PreBasicBlock bb, int i, Definition def, SimpleAssignable a) { - def = TExplicitPreSsaDef(bb, i, _, a) - or - def = TImplicitEntryPreSsaDef(_, bb, a) and i = -1 - or - def = TPhiPreSsaDef(bb, a) and i = -1 -} - -private newtype SsaRefKind = - SsaRead() or - SsaDef() - -private predicate ssaRef(PreBasicBlock bb, int i, SimpleAssignable a, SsaRefKind k) { - readAt(bb, i, _, a) and - k = SsaRead() - or - defAt(bb, i, _, a) and - k = SsaDef() -} - -private int ssaRefRank(PreBasicBlock bb, int i, SimpleAssignable a, SsaRefKind k) { - i = rank[result](int j | ssaRef(bb, j, a, _)) and - ssaRef(bb, i, a, k) -} - -private predicate defReachesRank(PreBasicBlock bb, Definition def, SimpleAssignable a, int rnk) { - exists(int i | - rnk = ssaRefRank(bb, i, a, SsaDef()) and - defAt(bb, i, def, a) - ) - or - defReachesRank(bb, def, a, rnk - 1) and - rnk = ssaRefRank(bb, _, a, SsaRead()) -} - -private int maxSsaRefRank(PreBasicBlock bb, SimpleAssignable a) { - result = ssaRefRank(bb, _, a, _) and - not result + 1 = ssaRefRank(bb, _, a, _) -} - -pragma[noinline] -private predicate ssaDefReachesEndOfBlockRec(PreBasicBlock bb, Definition def, SimpleAssignable a) { - exists(PreBasicBlock idom | ssaDefReachesEndOfBlock(idom, def, a) | idom.immediatelyDominates(bb)) -} - -predicate ssaDefReachesEndOfBlock(PreBasicBlock bb, Definition def, SimpleAssignable a) { - exists(int last | last = maxSsaRefRank(bb, a) | - defReachesRank(bb, def, a, last) and - liveAtExit(bb, a) - ) - or - ssaDefReachesEndOfBlockRec(bb, def, a) and - liveAtExit(bb, a) and - not ssaRef(bb, _, a, SsaDef()) -} - -private predicate ssaDefReachesReadWithinBlock( - SimpleAssignable a, Definition def, PreBasicBlock bb, int i -) { - defReachesRank(bb, def, a, ssaRefRank(bb, i, a, SsaRead())) -} - -private predicate ssaDefReachesRead(SimpleAssignable a, Definition def, PreBasicBlock bb, int i) { - ssaDefReachesReadWithinBlock(a, def, bb, i) - or - ssaRef(bb, i, a, SsaRead()) and - ssaDefReachesEndOfBlock(bb.getAPredecessor(), def, a) and - not ssaDefReachesReadWithinBlock(a, _, bb, i) -} - -private int ssaDefRank(Definition def, PreBasicBlock bb, int i) { - exists(SimpleAssignable a | - a = def.getAssignable() and - result = ssaRefRank(bb, i, a, _) - | - ssaDefReachesRead(a, def, bb, i) - or - defAt(bb, i, def, a) - ) -} - -private predicate varOccursInBlock(Definition def, PreBasicBlock bb, SimpleAssignable a) { - exists(ssaDefRank(def, bb, _)) and - a = def.getAssignable() -} - -pragma[noinline] -private PreBasicBlock getAMaybeLiveSuccessor(Definition def, PreBasicBlock bb) { - result = bb.getASuccessor() and - not varOccursInBlock(_, bb, def.getAssignable()) and - ssaDefReachesEndOfBlock(bb, def, _) -} - -private predicate varBlockReaches(Definition def, PreBasicBlock bb1, PreBasicBlock bb2) { - varOccursInBlock(def, bb1, _) and - bb2 = bb1.getASuccessor() - or - exists(PreBasicBlock mid | varBlockReaches(def, bb1, mid) | - bb2 = getAMaybeLiveSuccessor(def, mid) - ) -} - -private predicate varBlockReachesRead(Definition def, PreBasicBlock bb1, AssignableRead read) { - exists(PreBasicBlock bb2, int i2 | - varBlockReaches(def, bb1, bb2) and - ssaRefRank(bb2, i2, def.getAssignable(), SsaRead()) = 1 and - readAt(bb2, i2, read, _) - ) -} - -private predicate adjacentVarRead(Definition def, PreBasicBlock bb1, int i1, AssignableRead read) { - exists(int rankix, int i2 | - rankix = ssaDefRank(def, bb1, i1) and - rankix + 1 = ssaDefRank(def, bb1, i2) and - readAt(bb1, i2, read, _) - ) - or - ssaDefRank(def, bb1, i1) = maxSsaRefRank(bb1, def.getAssignable()) and - varBlockReachesRead(def, bb1, read) -} - -predicate firstReadSameVar(Definition def, AssignableRead read) { - exists(PreBasicBlock bb1, int i1 | - defAt(bb1, i1, def, _) and - adjacentVarRead(def, bb1, i1, read) - ) -} - -predicate adjacentReadPairSameVar(AssignableRead read1, AssignableRead read2) { - exists(Definition def, PreBasicBlock bb1, int i1 | - readAt(bb1, i1, read1, _) and - adjacentVarRead(def, bb1, i1, read2) - ) } diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll index c69f313c17b..0947059d873 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll @@ -6,10 +6,10 @@ import csharp private import Completion -private import PreSsa as PreSsa private import ControlFlowGraphImpl private import SuccessorTypes private import semmle.code.csharp.controlflow.ControlFlowGraph::ControlFlow +private import semmle.code.csharp.controlflow.internal.PreSsa /** The maximum number of splits allowed for a given node. */ private int maxSplits() { result = 5 } @@ -1143,9 +1143,7 @@ module BooleanSplitting { * another condition that reads the same SSA variable. */ private predicate firstDefCondition(ConditionBlock cb) { - exists(AssignableRead read | this.defConditionReachableFromRead(cb, read) | - PreSsa::firstReadSameVar(def, read) - ) + this.defConditionReachableFromRead(cb, def.getAFirstRead()) } override predicate correlatesConditions(ConditionBlock cb1, ConditionBlock cb2, boolean inverted) { @@ -1168,9 +1166,9 @@ module BooleanSplitting { ) } - override Callable getEnclosingCallable() { result = def.getCallable() } + override Callable getEnclosingCallable() { result = def.getBasicBlock().getEnclosingCallable() } - override string toString() { result = def.getAssignable().toString() } + override string toString() { result = def.getSourceVariable().toString() } override Location getLocation() { result = def.getLocation() } } @@ -1321,7 +1319,6 @@ module BooleanSplitting { module LoopSplitting { private import semmle.code.csharp.controlflow.Guards as Guards private import PreBasicBlocks - private import PreSsa /** Holds if `ce` is guarded by a (non-)empty check, as specified by `v`. */ private predicate emptinessGuarded( diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/pressa/SsaImplCommon.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/pressa/SsaImplCommon.qll new file mode 100644 index 00000000000..be01c05b8fa --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/pressa/SsaImplCommon.qll @@ -0,0 +1,619 @@ +/** + * Provides a language-independant implementation of static single assignment + * (SSA) form. + */ + +private import SsaImplSpecific + +private BasicBlock getABasicBlockPredecessor(BasicBlock bb) { getABasicBlockSuccessor(result) = bb } + +/** + * Liveness analysis (based on source variables) to restrict the size of the + * SSA representation. + */ +private module Liveness { + /** + * A classification of variable references into reads (of a given kind) and + * (certain or uncertain) writes. + */ + private newtype TRefKind = + Read(boolean certain) { certain in [false, true] } or + Write(boolean certain) { certain in [false, true] } + + private class RefKind extends TRefKind { + string toString() { + exists(boolean certain | this = Read(certain) and result = "read (" + certain + ")") + or + exists(boolean certain | this = Write(certain) and result = "write (" + certain + ")") + } + + int getOrder() { + this = Read(_) and + result = 0 + or + this = Write(_) and + result = 1 + } + } + + /** + * Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`. + */ + private predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) { + exists(boolean certain | variableRead(bb, i, v, certain) | k = Read(certain)) + or + exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain)) + } + + private newtype OrderedRefIndex = + MkOrderedRefIndex(int i, int tag) { + exists(RefKind rk | ref(_, i, _, rk) | tag = rk.getOrder()) + } + + private OrderedRefIndex refOrd(BasicBlock bb, int i, SourceVariable v, RefKind k, int ord) { + ref(bb, i, v, k) and + result = MkOrderedRefIndex(i, ord) and + ord = k.getOrder() + } + + /** + * Gets the (1-based) rank of the reference to `v` at the `i`th node of + * basic block `bb`, which has the given reference kind `k`. + * + * Reads are considered before writes when they happen at the same index. + */ + private int refRank(BasicBlock bb, int i, SourceVariable v, RefKind k) { + refOrd(bb, i, v, k, _) = + rank[result](int j, int ord, OrderedRefIndex res | + res = refOrd(bb, j, v, _, ord) + | + res order by j, ord + ) + } + + private int maxRefRank(BasicBlock bb, SourceVariable v) { + result = refRank(bb, _, v, _) and + not result + 1 = refRank(bb, _, v, _) + } + + /** + * Gets the (1-based) rank of the first reference to `v` inside basic block `bb` + * that is either a read or a certain write. + */ + private int firstReadOrCertainWrite(BasicBlock bb, SourceVariable v) { + result = + min(int r, RefKind k | + r = refRank(bb, _, v, k) and + k != Write(false) + | + r + ) + } + + /** + * Holds if source variable `v` is live at the beginning of basic block `bb`. + */ + predicate liveAtEntry(BasicBlock bb, SourceVariable v) { + // The first read or certain write to `v` inside `bb` is a read + refRank(bb, _, v, Read(_)) = firstReadOrCertainWrite(bb, v) + or + // There is no certain write to `v` inside `bb`, but `v` is live at entry + // to a successor basic block of `bb` + not exists(firstReadOrCertainWrite(bb, v)) and + liveAtExit(bb, v) + } + + /** + * Holds if source variable `v` is live at the end of basic block `bb`. + */ + predicate liveAtExit(BasicBlock bb, SourceVariable v) { + liveAtEntry(getABasicBlockSuccessor(bb), v) + } + + /** + * Holds if variable `v` is live in basic block `bb` at index `i`. + * The rank of `i` is `rnk` as defined by `refRank()`. + */ + private predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk) { + exists(RefKind kind | rnk = refRank(bb, i, v, kind) | + rnk = maxRefRank(bb, v) and + liveAtExit(bb, v) + or + ref(bb, i, v, kind) and + kind = Read(_) + or + exists(RefKind nextKind | + liveAtRank(bb, _, v, rnk + 1) and + rnk + 1 = refRank(bb, _, v, nextKind) and + nextKind != Write(true) + ) + ) + } + + /** + * Holds if variable `v` is live after the (certain or uncertain) write at + * index `i` inside basic block `bb`. + */ + predicate liveAfterWrite(BasicBlock bb, int i, SourceVariable v) { + exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk)) + } +} + +private import Liveness + +/** Holds if `bb1` strictly dominates `bb2`. */ +private predicate strictlyDominates(BasicBlock bb1, BasicBlock bb2) { + bb1 = getImmediateBasicBlockDominator+(bb2) +} + +/** Holds if `bb1` dominates a predecessor of `bb2`. */ +private predicate dominatesPredecessor(BasicBlock bb1, BasicBlock bb2) { + exists(BasicBlock pred | pred = getABasicBlockPredecessor(bb2) | + bb1 = pred + or + strictlyDominates(bb1, pred) + ) +} + +/** Holds if `df` is in the dominance frontier of `bb`. */ +private predicate inDominanceFrontier(BasicBlock bb, BasicBlock df) { + dominatesPredecessor(bb, df) and + not strictlyDominates(bb, df) +} + +/** + * Holds if `bb` is in the dominance frontier of a block containing a + * definition of `v`. + */ +pragma[noinline] +private predicate inDefDominanceFrontier(BasicBlock bb, SourceVariable v) { + exists(BasicBlock defbb, Definition def | + def.definesAt(v, defbb, _) and + inDominanceFrontier(defbb, bb) + ) +} + +cached +newtype TDefinition = + TWriteDef(SourceVariable v, BasicBlock bb, int i) { + variableWrite(bb, i, v, _) and + liveAfterWrite(bb, i, v) + } or + TPhiNode(SourceVariable v, BasicBlock bb) { + inDefDominanceFrontier(bb, v) and + liveAtEntry(bb, v) + } + +private module SsaDefReaches { + newtype TSsaRefKind = + SsaRead() or + SsaDef() + + /** + * A classification of SSA variable references into reads and definitions. + */ + class SsaRefKind extends TSsaRefKind { + string toString() { + this = SsaRead() and + result = "SsaRead" + or + this = SsaDef() and + result = "SsaDef" + } + + int getOrder() { + this = SsaRead() and + result = 0 + or + this = SsaDef() and + result = 1 + } + } + + /** + * Holds if the `i`th node of basic block `bb` is a reference to `v`, + * either a read (when `k` is `SsaRead()`) or an SSA definition (when `k` + * is `SsaDef()`). + * + * Unlike `Liveness::ref`, this includes `phi` nodes. + */ + predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { + variableRead(bb, i, v, _) and + k = SsaRead() + or + exists(Definition def | def.definesAt(v, bb, i)) and + k = SsaDef() + } + + private newtype OrderedSsaRefIndex = + MkOrderedSsaRefIndex(int i, SsaRefKind k) { ssaRef(_, i, _, k) } + + private OrderedSsaRefIndex ssaRefOrd(BasicBlock bb, int i, SourceVariable v, SsaRefKind k, int ord) { + ssaRef(bb, i, v, k) and + result = MkOrderedSsaRefIndex(i, k) and + ord = k.getOrder() + } + + /** + * Gets the (1-based) rank of the reference to `v` at the `i`th node of basic + * block `bb`, which has the given reference kind `k`. + * + * For example, if `bb` is a basic block with a phi node for `v` (considered + * to be at index -1), reads `v` at node 2, and defines it at node 5, we have: + * + * ```ql + * ssaRefRank(bb, -1, v, SsaDef()) = 1 // phi node + * ssaRefRank(bb, 2, v, Read()) = 2 // read at node 2 + * ssaRefRank(bb, 5, v, SsaDef()) = 3 // definition at node 5 + * ``` + * + * Reads are considered before writes when they happen at the same index. + */ + int ssaRefRank(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { + ssaRefOrd(bb, i, v, k, _) = + rank[result](int j, int ord, OrderedSsaRefIndex res | + res = ssaRefOrd(bb, j, v, _, ord) + | + res order by j, ord + ) + } + + int maxSsaRefRank(BasicBlock bb, SourceVariable v) { + result = ssaRefRank(bb, _, v, _) and + not result + 1 = ssaRefRank(bb, _, v, _) + } + + /** + * Holds if the SSA definition `def` reaches rank index `rnk` in its own + * basic block `bb`. + */ + predicate ssaDefReachesRank(BasicBlock bb, Definition def, int rnk, SourceVariable v) { + exists(int i | + rnk = ssaRefRank(bb, i, v, SsaDef()) and + def.definesAt(v, bb, i) + ) + or + ssaDefReachesRank(bb, def, rnk - 1, v) and + rnk = ssaRefRank(bb, _, v, SsaRead()) + } + + /** + * Holds if the SSA definition of `v` at `def` reaches index `i` in the same + * basic block `bb`, without crossing another SSA definition of `v`. + */ + predicate ssaDefReachesReadWithinBlock(SourceVariable v, Definition def, BasicBlock bb, int i) { + exists(int rnk | + ssaDefReachesRank(bb, def, rnk, v) and + rnk = ssaRefRank(bb, i, v, SsaRead()) and + variableRead(bb, i, v, _) + ) + } + + /** + * Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition + * `redef` in the same basic block, without crossing another SSA definition of `v`. + */ + predicate ssaDefReachesUncertainDefWithinBlock( + SourceVariable v, Definition def, UncertainWriteDefinition redef + ) { + exists(BasicBlock bb, int rnk, int i | + ssaDefReachesRank(bb, def, rnk, v) and + rnk = ssaRefRank(bb, i, v, SsaDef()) - 1 and + redef.definesAt(v, bb, i) + ) + } + + /** + * Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`. + */ + int ssaDefRank(Definition def, SourceVariable v, BasicBlock bb, int i, SsaRefKind k) { + v = def.getSourceVariable() and + result = ssaRefRank(bb, i, v, k) and + ( + ssaDefReachesRead(_, def, bb, i) + or + def.definesAt(_, bb, i) + ) + } + + predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v) { + exists(ssaDefRank(def, v, bb, _, _)) + } + + pragma[noinline] + private BasicBlock getAMaybeLiveSuccessor(Definition def, BasicBlock bb) { + result = getABasicBlockSuccessor(bb) and + not defOccursInBlock(_, bb, def.getSourceVariable()) and + ssaDefReachesEndOfBlock(bb, def, _) + } + + /** + * Holds if `def` is accessed in basic block `bb1` (either a read or a write), + * `bb2` is a transitive successor of `bb1`, `def` is live at the end of `bb1`, + * and the underlying variable for `def` is neither read nor written in any block + * on the path between `bb1` and `bb2`. + */ + predicate varBlockReaches(Definition def, BasicBlock bb1, BasicBlock bb2) { + defOccursInBlock(def, bb1, _) and + bb2 = getABasicBlockSuccessor(bb1) + or + exists(BasicBlock mid | varBlockReaches(def, bb1, mid) | bb2 = getAMaybeLiveSuccessor(def, mid)) + } + + /** + * Holds if `def` is accessed in basic block `bb1` (either a read or a write), + * `def` is read at index `i2` in basic block `bb2`, `bb2` is in a transitive + * successor block of `bb1`, and `def` is neither read nor written in any block + * on a path between `bb1` and `bb2`. + */ + predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) { + varBlockReaches(def, bb1, bb2) and + ssaRefRank(bb2, i2, def.getSourceVariable(), SsaRead()) = 1 and + variableRead(bb2, i2, _, _) + } +} + +private import SsaDefReaches + +pragma[noinline] +private predicate ssaDefReachesEndOfBlockRec(BasicBlock bb, Definition def, SourceVariable v) { + exists(BasicBlock idom | ssaDefReachesEndOfBlock(idom, def, v) | + // The construction of SSA form ensures that each read of a variable is + // dominated by its definition. An SSA definition therefore reaches a + // control flow node if it is the _closest_ SSA definition that dominates + // the node. If two definitions dominate a node then one must dominate the + // other, so therefore the definition of _closest_ is given by the dominator + // tree. Thus, reaching definitions can be calculated in terms of dominance. + idom = getImmediateBasicBlockDominator(bb) + ) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Holds if the SSA definition of `v` at `def` reaches the end of basic + * block `bb`, at which point it is still live, without crossing another + * SSA definition of `v`. + */ +pragma[nomagic] +predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) { + exists(int last | last = maxSsaRefRank(bb, v) | + ssaDefReachesRank(bb, def, last, v) and + liveAtExit(bb, v) + ) + or + ssaDefReachesEndOfBlockRec(bb, def, v) and + liveAtExit(bb, v) and + not ssaRef(bb, _, v, SsaDef()) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Holds if `inp` is an input to the phi node `phi` along the edge originating in `bb`. + */ +pragma[nomagic] +predicate phiHasInputFromBlock(PhiNode phi, Definition inp, BasicBlock bb) { + exists(SourceVariable v, BasicBlock bbDef | + phi.definesAt(v, bbDef, _) and + getABasicBlockPredecessor(bbDef) = bb and + ssaDefReachesEndOfBlock(bb, inp, v) + ) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Holds if the SSA definition of `v` at `def` reaches a read at index `i` in + * basic block `bb`, without crossing another SSA definition of `v`. The read + * is of kind `rk`. + */ +pragma[nomagic] +predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i) { + ssaDefReachesReadWithinBlock(v, def, bb, i) + or + variableRead(bb, i, v, _) and + ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and + not ssaDefReachesReadWithinBlock(v, _, bb, i) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Holds if `def` is accessed at index `i1` in basic block `bb1` (either a read + * or a write), `def` is read at index `i2` in basic block `bb2`, and there is a + * path between them without any read of `def`. + */ +pragma[nomagic] +predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) { + exists(int rnk | + rnk = ssaDefRank(def, _, bb1, i1, _) and + rnk + 1 = ssaDefRank(def, _, bb1, i2, SsaRead()) and + variableRead(bb1, i2, _, _) and + bb2 = bb1 + ) + or + exists(SourceVariable v | ssaDefRank(def, v, bb1, i1, _) = maxSsaRefRank(bb1, v)) and + defAdjacentRead(def, bb1, bb2, i2) +} + +private predicate adjacentDefReachesRead( + Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2 +) { + adjacentDefRead(def, bb1, i1, bb2, i2) and + exists(SourceVariable v | v = def.getSourceVariable() | + ssaRef(bb1, i1, v, SsaDef()) + or + variableRead(bb1, i1, v, true) + ) + or + exists(BasicBlock bb3, int i3 | + adjacentDefReachesRead(def, bb1, i1, bb3, i3) and + variableRead(bb3, i3, _, false) and + adjacentDefRead(def, bb3, i3, bb2, i2) + ) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Same as `adjacentDefRead`, but ignores uncertain reads. + */ +pragma[nomagic] +predicate adjacentDefNoUncertainReads(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) { + adjacentDefReachesRead(def, bb1, i1, bb2, i2) and + variableRead(bb2, i2, _, true) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Holds if the node at index `i` in `bb` is a last reference to SSA definition + * `def`. The reference is last because it can reach another write `next`, + * without passing through another read or write. + */ +pragma[nomagic] +predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) { + exists(int rnk, SourceVariable v, int j | rnk = ssaDefRank(def, v, bb, i, _) | + // Next reference to `v` inside `bb` is a write + next.definesAt(v, bb, j) and + rnk + 1 = ssaRefRank(bb, j, v, SsaDef()) + or + // Can reach a write using one or more steps + rnk = maxSsaRefRank(bb, v) and + exists(BasicBlock bb2 | + varBlockReaches(def, bb, bb2) and + next.definesAt(v, bb2, j) and + 1 = ssaRefRank(bb2, j, v, SsaDef()) + ) + ) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Holds if `inp` is an immediately preceding definition of uncertain definition + * `def`. Since `def` is uncertain, the value from the preceding definition might + * still be valid. + */ +pragma[nomagic] +predicate uncertainWriteDefinitionInput(UncertainWriteDefinition def, Definition inp) { + lastRefRedef(inp, _, _, def) +} + +private predicate adjacentDefReachesUncertainRead( + Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2 +) { + adjacentDefReachesRead(def, bb1, i1, bb2, i2) and + variableRead(bb2, i2, _, false) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Same as `lastRefRedef`, but ignores uncertain reads. + */ +pragma[nomagic] +predicate lastRefRedefNoUncertainReads(Definition def, BasicBlock bb, int i, Definition next) { + lastRefRedef(def, bb, i, next) and + not variableRead(bb, i, def.getSourceVariable(), false) + or + exists(BasicBlock bb0, int i0 | + lastRefRedef(def, bb0, i0, next) and + adjacentDefReachesUncertainRead(def, bb, i, bb0, i0) + ) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Holds if the node at index `i` in `bb` is a last reference to SSA + * definition `def`. + * + * That is, the node can reach the end of the enclosing callable, or another + * SSA definition for the underlying source variable, without passing through + * another read. + */ +pragma[nomagic] +predicate lastRef(Definition def, BasicBlock bb, int i) { + lastRefRedef(def, bb, i, _) + or + exists(SourceVariable v | ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v) | + // Can reach exit directly + bb instanceof ExitBasicBlock + or + // Can reach a block using one or more steps, where `def` is no longer live + exists(BasicBlock bb2 | varBlockReaches(def, bb, bb2) | + not defOccursInBlock(def, bb2, _) and + not ssaDefReachesEndOfBlock(bb2, def, _) + ) + ) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Same as `lastRefRedef`, but ignores uncertain reads. + */ +pragma[nomagic] +predicate lastRefNoUncertainReads(Definition def, BasicBlock bb, int i) { + lastRef(def, bb, i) and + not variableRead(bb, i, def.getSourceVariable(), false) + or + exists(BasicBlock bb0, int i0 | + lastRef(def, bb0, i0) and + adjacentDefReachesUncertainRead(def, bb, i, bb0, i0) + ) +} + +/** A static single assignment (SSA) definition. */ +class Definition extends TDefinition { + /** Gets the source variable underlying this SSA definition. */ + SourceVariable getSourceVariable() { this.definesAt(result, _, _) } + + /** + * Holds if this SSA definition defines `v` at index `i` in basic block `bb`. + * Phi nodes are considered to be at index `-1`, while normal variable writes + * are at the index of the control flow node they wrap. + */ + final predicate definesAt(SourceVariable v, BasicBlock bb, int i) { + this = TWriteDef(v, bb, i) + or + this = TPhiNode(v, bb) and i = -1 + } + + /** Gets the basic block to which this SSA definition belongs. */ + final BasicBlock getBasicBlock() { this.definesAt(_, result, _) } + + /** Gets a textual representation of this SSA definition. */ + string toString() { none() } +} + +/** An SSA definition that corresponds to a write. */ +class WriteDefinition extends Definition, TWriteDef { + private SourceVariable v; + private BasicBlock bb; + private int i; + + WriteDefinition() { this = TWriteDef(v, bb, i) } + + override string toString() { result = "WriteDef" } +} + +/** A phi node. */ +class PhiNode extends Definition, TPhiNode { + override string toString() { result = "Phi" } +} + +/** + * An SSA definition that represents an uncertain update of the underlying + * source variable. + */ +class UncertainWriteDefinition extends WriteDefinition { + UncertainWriteDefinition() { + exists(SourceVariable v, BasicBlock bb, int i | + this.definesAt(v, bb, i) and + variableWrite(bb, i, v, false) + ) + } +} diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/pressa/SsaImplSpecific.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/pressa/SsaImplSpecific.qll new file mode 100644 index 00000000000..610e808a640 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/pressa/SsaImplSpecific.qll @@ -0,0 +1,106 @@ +/** Provides the C# specific parameters for `SsaImplCommon.qll`. */ + +private import csharp +private import AssignableDefinitions +private import semmle.code.csharp.controlflow.internal.PreBasicBlocks as PreBasicBlocks +private import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl + +class BasicBlock = PreBasicBlocks::PreBasicBlock; + +BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) } + +BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() } + +class ExitBasicBlock extends BasicBlock { + ExitBasicBlock() { scopeLast(_, this.getLastElement(), _) } +} + +pragma[noinline] +private predicate assignableNoCapturing(Assignable a, Callable c) { + exists(AssignableAccess aa | aa.getTarget() = a | c = aa.getEnclosingCallable()) and + forall(AssignableDefinition def | def.getTarget() = a | + c = def.getEnclosingCallable() + or + def.getEnclosingCallable() instanceof Constructor + ) +} + +pragma[noinline] +private predicate assignableNoComplexQualifiers(Assignable a) { + forall(QualifiableExpr qe | qe.(AssignableAccess).getTarget() = a | qe.targetIsThisInstance()) +} + +/** + * A simple assignable. Either a local scope variable or a field/property + * that behaves like a local scope variable. + */ +class SourceVariable extends Assignable { + private Callable c; + + SourceVariable() { + ( + this instanceof LocalScopeVariable + or + this instanceof Field + or + this = any(TrivialProperty tp | not tp.isOverridableOrImplementable()) + ) and + assignableNoCapturing(this, c) and + assignableNoComplexQualifiers(this) + } + + /** Gets a callable in which this simple assignable can be analyzed. */ + Callable getACallable() { result = c } +} + +predicate definitionAt(AssignableDefinition def, BasicBlock bb, int i, SourceVariable v) { + bb.getElement(i) = def.getExpr() and + v = def.getTarget() and + // In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x` + not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | first = def | + second.getAssignment() = first.getAssignment() and + second.getEvaluationOrder() > first.getEvaluationOrder() and + second.getTarget() = v + ) + or + def.(ImplicitParameterDefinition).getParameter() = v and + exists(Callable c | v = c.getAParameter() | + scopeFirst(c, bb) and + i = -1 + ) +} + +predicate implicitEntryDef(Callable c, BasicBlock bb, SourceVariable v) { + not v instanceof LocalScopeVariable and + c = v.getACallable() and + scopeFirst(c, bb) +} + +predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) { + exists(AssignableDefinition def | + definitionAt(def, bb, i, v) and + if def.getTargetAccess().isRefArgument() then certain = false else certain = true + ) + or + exists(Callable c | + implicitEntryDef(c, bb, v) and + i = -1 and + certain = true + ) +} + +predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) { + exists(AssignableRead read | + read = bb.getElement(i) and + read.getTarget() = v and + certain = true + ) + or + v = + any(LocalScopeVariable lsv | + lsv.getCallable() = bb.(ExitBasicBlock).getEnclosingCallable() and + i = bb.length() and + (lsv.isRef() or v.(Parameter).isOut()) and + certain = false + ) +} diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/BaseSSA.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/BaseSSA.qll index 584e0ca9c33..281523a2fbd 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/BaseSSA.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/BaseSSA.qll @@ -1,125 +1,43 @@ import csharp /** - * INTERNAL: Do not use. - * * Provides a simple SSA implementation for local scope variables. */ module BaseSsa { - private import ControlFlow - private import AssignableDefinitions + import basessa.SsaImplSpecific + private import basessa.SsaImplCommon as SsaImpl - pragma[noinline] - Callable getAnAssigningCallable(LocalScopeVariable v) { - result = any(AssignableDefinition def | def.getTarget() = v).getEnclosingCallable() + class Definition extends SsaImpl::Definition { + final AssignableRead getARead() { + exists(BasicBlock bb, int i | + SsaImpl::ssaDefReachesRead(_, this, bb, i) and + result.getAControlFlowNode() = bb.getNode(i) + ) + } + + final AssignableDefinition getDefinition() { + exists(BasicBlock bb, int i, SourceVariable v | + this.definesAt(v, bb, i) and + definitionAt(result, bb, i, v) + ) + } + + private Definition getAPhiInputOrPriorDefinition() { + result = this.(PhiNode).getAnInput() or + SsaImpl::uncertainWriteDefinitionInput(this, result) + } + + final Definition getAnUltimateDefinition() { + result = this.getAPhiInputOrPriorDefinition*() and + not result instanceof PhiNode + } + + Location getLocation() { result = this.getDefinition().getLocation() } } - private class SimpleLocalScopeVariable extends LocalScopeVariable { - SimpleLocalScopeVariable() { not getAnAssigningCallable(this) != getAnAssigningCallable(this) } - } + class PhiNode extends SsaImpl::PhiNode, Definition { + override Location getLocation() { result = this.getBasicBlock().getLocation() } - /** - * Holds if the `i`th node of basic block `bb` is assignable definition `def`, - * targeting local scope variable `v`. - */ - private predicate defAt(BasicBlock bb, int i, AssignableDefinition def, SimpleLocalScopeVariable v) { - bb.getNode(i) = def.getAControlFlowNode() and - v = def.getTarget() and - // In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x` - not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | first = def | - second.getAssignment() = first.getAssignment() and - second.getEvaluationOrder() > first.getEvaluationOrder() and - second.getTarget() = v - ) - } - - /** - * Holds if basic block `bb` would need to start with a phi node for local scope - * variable `v` in an SSA representation. - */ - private predicate needsPhiNode(BasicBlock bb, SimpleLocalScopeVariable v) { - exists(BasicBlock def | def.inDominanceFrontier(bb) | - defAt(def, _, _, v) or - needsPhiNode(def, v) - ) - } - - private newtype SsaRefKind = - SsaRead() or - SsaDef() - - /** - * Holds if the `i`th node of basic block `bb` is a reference to `v`, - * either a read (when `k` is `SsaRead()`) or a write including phi nodes - * (when `k` is `SsaDef()`). - */ - private predicate ssaRef(BasicBlock bb, int i, SimpleLocalScopeVariable v, SsaRefKind k) { - bb.getNode(i).getElement() = v.getAnAccess().(VariableRead) and - k = SsaRead() - or - defAt(bb, i, _, v) and - k = SsaDef() - or - needsPhiNode(bb, v) and - i = -1 and - k = SsaDef() - } - - /** - * Gets the (1-based) rank of the reference to `v` at the `i`th node of basic - * block `bb`, which has the given reference kind `k`. - */ - private int ssaRefRank(BasicBlock bb, int i, SimpleLocalScopeVariable v, SsaRefKind k) { - i = rank[result](int j | ssaRef(bb, j, v, _)) and - ssaRef(bb, i, v, k) - } - - /** - * Holds if definition `def` of local scope variable `v` inside basic block - * `bb` reaches the reference at rank `rnk`, without passing through another - * definition of `v`, including phi nodes. - */ - private predicate defReachesRank( - BasicBlock bb, AssignableDefinition def, SimpleLocalScopeVariable v, int rnk - ) { - exists(int i | rnk = ssaRefRank(bb, i, v, SsaDef()) | defAt(bb, i, def, v)) - or - defReachesRank(bb, def, v, rnk - 1) and - rnk = ssaRefRank(bb, _, v, SsaRead()) - } - - /** - * Holds if definition `def` of local scope variable `v` reaches the end of - * basic block `bb` without passing through another definition of `v`, including - * phi nodes. - */ - private predicate reachesEndOf(AssignableDefinition def, SimpleLocalScopeVariable v, BasicBlock bb) { - exists(int rnk | - defReachesRank(bb, def, v, rnk) and - rnk = max(ssaRefRank(bb, _, v, _)) - ) - or - exists(BasicBlock mid | - reachesEndOf(def, v, mid) and - not exists(ssaRefRank(mid, _, v, SsaDef())) and - bb = mid.getASuccessor() - ) - } - - /** - * Gets a read of the SSA definition for variable `v` at definition `def`. That is, - * a read that is guaranteed to read the value assigned at definition `def`. - */ - cached - AssignableRead getARead(AssignableDefinition def, SimpleLocalScopeVariable v) { - exists(BasicBlock bb, int i, int rnk | - result.getAControlFlowNode() = bb.getNode(i) and - rnk = ssaRefRank(bb, i, v, SsaRead()) - | - defReachesRank(bb, def, v, rnk) - or - reachesEndOf(def, v, bb.getAPredecessor()) and - not ssaRefRank(bb, _, v, SsaDef()) < rnk - ) + final Definition getAnInput() { SsaImpl::phiHasInputFromBlock(this, result, _) } } } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll index 1d2e9052842..54f41545284 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -415,6 +415,30 @@ private module Cached { store(node1, tc.getContent(), node2, contentType, tc.getContainerType()) } + /** + * Holds if data can flow from `fromNode` to `toNode` because they are the post-update + * nodes of some function output and input respectively, where the output and input + * are aliases. A typical example is a function returning `this`, implementing a fluent + * interface. + */ + cached + predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) { + exists(Node fromPre, Node toPre | + fromPre = fromNode.getPreUpdateNode() and + toPre = toNode.getPreUpdateNode() + | + exists(DataFlowCall c | + // Does the language-specific simpleLocalFlowStep already model flow + // from function input to output? + fromPre = getAnOutNode(c, _) and + toPre.(ArgumentNode).argumentOf(c, _) and + simpleLocalFlowStep(toPre.(ArgumentNode), fromPre) + ) + or + argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre) + ) + } + /** * Holds if the call context `call` either improves virtual dispatch in * `callable` or if it allows us to prune unreachable nodes in `callable`. diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/Steps.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/Steps.qll index d29d6b1e10b..54cafff994a 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/Steps.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/Steps.qll @@ -16,7 +16,10 @@ module Steps { * Gets a read that is guaranteed to read the value assigned at definition `def`. */ private AssignableRead getARead(AssignableDefinition def) { - result = BaseSsa::getARead(def, _) + exists(BaseSsa::Definition ssaDef | + ssaDef.getDefinition() = def and + result = ssaDef.getARead() + ) or exists(LocalScopeVariable v | def.getTarget() = v | result = v.getAnAccess() and diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/basessa/SsaImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/basessa/SsaImplCommon.qll new file mode 100644 index 00000000000..be01c05b8fa --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/basessa/SsaImplCommon.qll @@ -0,0 +1,619 @@ +/** + * Provides a language-independant implementation of static single assignment + * (SSA) form. + */ + +private import SsaImplSpecific + +private BasicBlock getABasicBlockPredecessor(BasicBlock bb) { getABasicBlockSuccessor(result) = bb } + +/** + * Liveness analysis (based on source variables) to restrict the size of the + * SSA representation. + */ +private module Liveness { + /** + * A classification of variable references into reads (of a given kind) and + * (certain or uncertain) writes. + */ + private newtype TRefKind = + Read(boolean certain) { certain in [false, true] } or + Write(boolean certain) { certain in [false, true] } + + private class RefKind extends TRefKind { + string toString() { + exists(boolean certain | this = Read(certain) and result = "read (" + certain + ")") + or + exists(boolean certain | this = Write(certain) and result = "write (" + certain + ")") + } + + int getOrder() { + this = Read(_) and + result = 0 + or + this = Write(_) and + result = 1 + } + } + + /** + * Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`. + */ + private predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) { + exists(boolean certain | variableRead(bb, i, v, certain) | k = Read(certain)) + or + exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain)) + } + + private newtype OrderedRefIndex = + MkOrderedRefIndex(int i, int tag) { + exists(RefKind rk | ref(_, i, _, rk) | tag = rk.getOrder()) + } + + private OrderedRefIndex refOrd(BasicBlock bb, int i, SourceVariable v, RefKind k, int ord) { + ref(bb, i, v, k) and + result = MkOrderedRefIndex(i, ord) and + ord = k.getOrder() + } + + /** + * Gets the (1-based) rank of the reference to `v` at the `i`th node of + * basic block `bb`, which has the given reference kind `k`. + * + * Reads are considered before writes when they happen at the same index. + */ + private int refRank(BasicBlock bb, int i, SourceVariable v, RefKind k) { + refOrd(bb, i, v, k, _) = + rank[result](int j, int ord, OrderedRefIndex res | + res = refOrd(bb, j, v, _, ord) + | + res order by j, ord + ) + } + + private int maxRefRank(BasicBlock bb, SourceVariable v) { + result = refRank(bb, _, v, _) and + not result + 1 = refRank(bb, _, v, _) + } + + /** + * Gets the (1-based) rank of the first reference to `v` inside basic block `bb` + * that is either a read or a certain write. + */ + private int firstReadOrCertainWrite(BasicBlock bb, SourceVariable v) { + result = + min(int r, RefKind k | + r = refRank(bb, _, v, k) and + k != Write(false) + | + r + ) + } + + /** + * Holds if source variable `v` is live at the beginning of basic block `bb`. + */ + predicate liveAtEntry(BasicBlock bb, SourceVariable v) { + // The first read or certain write to `v` inside `bb` is a read + refRank(bb, _, v, Read(_)) = firstReadOrCertainWrite(bb, v) + or + // There is no certain write to `v` inside `bb`, but `v` is live at entry + // to a successor basic block of `bb` + not exists(firstReadOrCertainWrite(bb, v)) and + liveAtExit(bb, v) + } + + /** + * Holds if source variable `v` is live at the end of basic block `bb`. + */ + predicate liveAtExit(BasicBlock bb, SourceVariable v) { + liveAtEntry(getABasicBlockSuccessor(bb), v) + } + + /** + * Holds if variable `v` is live in basic block `bb` at index `i`. + * The rank of `i` is `rnk` as defined by `refRank()`. + */ + private predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk) { + exists(RefKind kind | rnk = refRank(bb, i, v, kind) | + rnk = maxRefRank(bb, v) and + liveAtExit(bb, v) + or + ref(bb, i, v, kind) and + kind = Read(_) + or + exists(RefKind nextKind | + liveAtRank(bb, _, v, rnk + 1) and + rnk + 1 = refRank(bb, _, v, nextKind) and + nextKind != Write(true) + ) + ) + } + + /** + * Holds if variable `v` is live after the (certain or uncertain) write at + * index `i` inside basic block `bb`. + */ + predicate liveAfterWrite(BasicBlock bb, int i, SourceVariable v) { + exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk)) + } +} + +private import Liveness + +/** Holds if `bb1` strictly dominates `bb2`. */ +private predicate strictlyDominates(BasicBlock bb1, BasicBlock bb2) { + bb1 = getImmediateBasicBlockDominator+(bb2) +} + +/** Holds if `bb1` dominates a predecessor of `bb2`. */ +private predicate dominatesPredecessor(BasicBlock bb1, BasicBlock bb2) { + exists(BasicBlock pred | pred = getABasicBlockPredecessor(bb2) | + bb1 = pred + or + strictlyDominates(bb1, pred) + ) +} + +/** Holds if `df` is in the dominance frontier of `bb`. */ +private predicate inDominanceFrontier(BasicBlock bb, BasicBlock df) { + dominatesPredecessor(bb, df) and + not strictlyDominates(bb, df) +} + +/** + * Holds if `bb` is in the dominance frontier of a block containing a + * definition of `v`. + */ +pragma[noinline] +private predicate inDefDominanceFrontier(BasicBlock bb, SourceVariable v) { + exists(BasicBlock defbb, Definition def | + def.definesAt(v, defbb, _) and + inDominanceFrontier(defbb, bb) + ) +} + +cached +newtype TDefinition = + TWriteDef(SourceVariable v, BasicBlock bb, int i) { + variableWrite(bb, i, v, _) and + liveAfterWrite(bb, i, v) + } or + TPhiNode(SourceVariable v, BasicBlock bb) { + inDefDominanceFrontier(bb, v) and + liveAtEntry(bb, v) + } + +private module SsaDefReaches { + newtype TSsaRefKind = + SsaRead() or + SsaDef() + + /** + * A classification of SSA variable references into reads and definitions. + */ + class SsaRefKind extends TSsaRefKind { + string toString() { + this = SsaRead() and + result = "SsaRead" + or + this = SsaDef() and + result = "SsaDef" + } + + int getOrder() { + this = SsaRead() and + result = 0 + or + this = SsaDef() and + result = 1 + } + } + + /** + * Holds if the `i`th node of basic block `bb` is a reference to `v`, + * either a read (when `k` is `SsaRead()`) or an SSA definition (when `k` + * is `SsaDef()`). + * + * Unlike `Liveness::ref`, this includes `phi` nodes. + */ + predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { + variableRead(bb, i, v, _) and + k = SsaRead() + or + exists(Definition def | def.definesAt(v, bb, i)) and + k = SsaDef() + } + + private newtype OrderedSsaRefIndex = + MkOrderedSsaRefIndex(int i, SsaRefKind k) { ssaRef(_, i, _, k) } + + private OrderedSsaRefIndex ssaRefOrd(BasicBlock bb, int i, SourceVariable v, SsaRefKind k, int ord) { + ssaRef(bb, i, v, k) and + result = MkOrderedSsaRefIndex(i, k) and + ord = k.getOrder() + } + + /** + * Gets the (1-based) rank of the reference to `v` at the `i`th node of basic + * block `bb`, which has the given reference kind `k`. + * + * For example, if `bb` is a basic block with a phi node for `v` (considered + * to be at index -1), reads `v` at node 2, and defines it at node 5, we have: + * + * ```ql + * ssaRefRank(bb, -1, v, SsaDef()) = 1 // phi node + * ssaRefRank(bb, 2, v, Read()) = 2 // read at node 2 + * ssaRefRank(bb, 5, v, SsaDef()) = 3 // definition at node 5 + * ``` + * + * Reads are considered before writes when they happen at the same index. + */ + int ssaRefRank(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { + ssaRefOrd(bb, i, v, k, _) = + rank[result](int j, int ord, OrderedSsaRefIndex res | + res = ssaRefOrd(bb, j, v, _, ord) + | + res order by j, ord + ) + } + + int maxSsaRefRank(BasicBlock bb, SourceVariable v) { + result = ssaRefRank(bb, _, v, _) and + not result + 1 = ssaRefRank(bb, _, v, _) + } + + /** + * Holds if the SSA definition `def` reaches rank index `rnk` in its own + * basic block `bb`. + */ + predicate ssaDefReachesRank(BasicBlock bb, Definition def, int rnk, SourceVariable v) { + exists(int i | + rnk = ssaRefRank(bb, i, v, SsaDef()) and + def.definesAt(v, bb, i) + ) + or + ssaDefReachesRank(bb, def, rnk - 1, v) and + rnk = ssaRefRank(bb, _, v, SsaRead()) + } + + /** + * Holds if the SSA definition of `v` at `def` reaches index `i` in the same + * basic block `bb`, without crossing another SSA definition of `v`. + */ + predicate ssaDefReachesReadWithinBlock(SourceVariable v, Definition def, BasicBlock bb, int i) { + exists(int rnk | + ssaDefReachesRank(bb, def, rnk, v) and + rnk = ssaRefRank(bb, i, v, SsaRead()) and + variableRead(bb, i, v, _) + ) + } + + /** + * Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition + * `redef` in the same basic block, without crossing another SSA definition of `v`. + */ + predicate ssaDefReachesUncertainDefWithinBlock( + SourceVariable v, Definition def, UncertainWriteDefinition redef + ) { + exists(BasicBlock bb, int rnk, int i | + ssaDefReachesRank(bb, def, rnk, v) and + rnk = ssaRefRank(bb, i, v, SsaDef()) - 1 and + redef.definesAt(v, bb, i) + ) + } + + /** + * Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`. + */ + int ssaDefRank(Definition def, SourceVariable v, BasicBlock bb, int i, SsaRefKind k) { + v = def.getSourceVariable() and + result = ssaRefRank(bb, i, v, k) and + ( + ssaDefReachesRead(_, def, bb, i) + or + def.definesAt(_, bb, i) + ) + } + + predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v) { + exists(ssaDefRank(def, v, bb, _, _)) + } + + pragma[noinline] + private BasicBlock getAMaybeLiveSuccessor(Definition def, BasicBlock bb) { + result = getABasicBlockSuccessor(bb) and + not defOccursInBlock(_, bb, def.getSourceVariable()) and + ssaDefReachesEndOfBlock(bb, def, _) + } + + /** + * Holds if `def` is accessed in basic block `bb1` (either a read or a write), + * `bb2` is a transitive successor of `bb1`, `def` is live at the end of `bb1`, + * and the underlying variable for `def` is neither read nor written in any block + * on the path between `bb1` and `bb2`. + */ + predicate varBlockReaches(Definition def, BasicBlock bb1, BasicBlock bb2) { + defOccursInBlock(def, bb1, _) and + bb2 = getABasicBlockSuccessor(bb1) + or + exists(BasicBlock mid | varBlockReaches(def, bb1, mid) | bb2 = getAMaybeLiveSuccessor(def, mid)) + } + + /** + * Holds if `def` is accessed in basic block `bb1` (either a read or a write), + * `def` is read at index `i2` in basic block `bb2`, `bb2` is in a transitive + * successor block of `bb1`, and `def` is neither read nor written in any block + * on a path between `bb1` and `bb2`. + */ + predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) { + varBlockReaches(def, bb1, bb2) and + ssaRefRank(bb2, i2, def.getSourceVariable(), SsaRead()) = 1 and + variableRead(bb2, i2, _, _) + } +} + +private import SsaDefReaches + +pragma[noinline] +private predicate ssaDefReachesEndOfBlockRec(BasicBlock bb, Definition def, SourceVariable v) { + exists(BasicBlock idom | ssaDefReachesEndOfBlock(idom, def, v) | + // The construction of SSA form ensures that each read of a variable is + // dominated by its definition. An SSA definition therefore reaches a + // control flow node if it is the _closest_ SSA definition that dominates + // the node. If two definitions dominate a node then one must dominate the + // other, so therefore the definition of _closest_ is given by the dominator + // tree. Thus, reaching definitions can be calculated in terms of dominance. + idom = getImmediateBasicBlockDominator(bb) + ) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Holds if the SSA definition of `v` at `def` reaches the end of basic + * block `bb`, at which point it is still live, without crossing another + * SSA definition of `v`. + */ +pragma[nomagic] +predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) { + exists(int last | last = maxSsaRefRank(bb, v) | + ssaDefReachesRank(bb, def, last, v) and + liveAtExit(bb, v) + ) + or + ssaDefReachesEndOfBlockRec(bb, def, v) and + liveAtExit(bb, v) and + not ssaRef(bb, _, v, SsaDef()) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Holds if `inp` is an input to the phi node `phi` along the edge originating in `bb`. + */ +pragma[nomagic] +predicate phiHasInputFromBlock(PhiNode phi, Definition inp, BasicBlock bb) { + exists(SourceVariable v, BasicBlock bbDef | + phi.definesAt(v, bbDef, _) and + getABasicBlockPredecessor(bbDef) = bb and + ssaDefReachesEndOfBlock(bb, inp, v) + ) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Holds if the SSA definition of `v` at `def` reaches a read at index `i` in + * basic block `bb`, without crossing another SSA definition of `v`. The read + * is of kind `rk`. + */ +pragma[nomagic] +predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i) { + ssaDefReachesReadWithinBlock(v, def, bb, i) + or + variableRead(bb, i, v, _) and + ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and + not ssaDefReachesReadWithinBlock(v, _, bb, i) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Holds if `def` is accessed at index `i1` in basic block `bb1` (either a read + * or a write), `def` is read at index `i2` in basic block `bb2`, and there is a + * path between them without any read of `def`. + */ +pragma[nomagic] +predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) { + exists(int rnk | + rnk = ssaDefRank(def, _, bb1, i1, _) and + rnk + 1 = ssaDefRank(def, _, bb1, i2, SsaRead()) and + variableRead(bb1, i2, _, _) and + bb2 = bb1 + ) + or + exists(SourceVariable v | ssaDefRank(def, v, bb1, i1, _) = maxSsaRefRank(bb1, v)) and + defAdjacentRead(def, bb1, bb2, i2) +} + +private predicate adjacentDefReachesRead( + Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2 +) { + adjacentDefRead(def, bb1, i1, bb2, i2) and + exists(SourceVariable v | v = def.getSourceVariable() | + ssaRef(bb1, i1, v, SsaDef()) + or + variableRead(bb1, i1, v, true) + ) + or + exists(BasicBlock bb3, int i3 | + adjacentDefReachesRead(def, bb1, i1, bb3, i3) and + variableRead(bb3, i3, _, false) and + adjacentDefRead(def, bb3, i3, bb2, i2) + ) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Same as `adjacentDefRead`, but ignores uncertain reads. + */ +pragma[nomagic] +predicate adjacentDefNoUncertainReads(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) { + adjacentDefReachesRead(def, bb1, i1, bb2, i2) and + variableRead(bb2, i2, _, true) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Holds if the node at index `i` in `bb` is a last reference to SSA definition + * `def`. The reference is last because it can reach another write `next`, + * without passing through another read or write. + */ +pragma[nomagic] +predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) { + exists(int rnk, SourceVariable v, int j | rnk = ssaDefRank(def, v, bb, i, _) | + // Next reference to `v` inside `bb` is a write + next.definesAt(v, bb, j) and + rnk + 1 = ssaRefRank(bb, j, v, SsaDef()) + or + // Can reach a write using one or more steps + rnk = maxSsaRefRank(bb, v) and + exists(BasicBlock bb2 | + varBlockReaches(def, bb, bb2) and + next.definesAt(v, bb2, j) and + 1 = ssaRefRank(bb2, j, v, SsaDef()) + ) + ) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Holds if `inp` is an immediately preceding definition of uncertain definition + * `def`. Since `def` is uncertain, the value from the preceding definition might + * still be valid. + */ +pragma[nomagic] +predicate uncertainWriteDefinitionInput(UncertainWriteDefinition def, Definition inp) { + lastRefRedef(inp, _, _, def) +} + +private predicate adjacentDefReachesUncertainRead( + Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2 +) { + adjacentDefReachesRead(def, bb1, i1, bb2, i2) and + variableRead(bb2, i2, _, false) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Same as `lastRefRedef`, but ignores uncertain reads. + */ +pragma[nomagic] +predicate lastRefRedefNoUncertainReads(Definition def, BasicBlock bb, int i, Definition next) { + lastRefRedef(def, bb, i, next) and + not variableRead(bb, i, def.getSourceVariable(), false) + or + exists(BasicBlock bb0, int i0 | + lastRefRedef(def, bb0, i0, next) and + adjacentDefReachesUncertainRead(def, bb, i, bb0, i0) + ) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Holds if the node at index `i` in `bb` is a last reference to SSA + * definition `def`. + * + * That is, the node can reach the end of the enclosing callable, or another + * SSA definition for the underlying source variable, without passing through + * another read. + */ +pragma[nomagic] +predicate lastRef(Definition def, BasicBlock bb, int i) { + lastRefRedef(def, bb, i, _) + or + exists(SourceVariable v | ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v) | + // Can reach exit directly + bb instanceof ExitBasicBlock + or + // Can reach a block using one or more steps, where `def` is no longer live + exists(BasicBlock bb2 | varBlockReaches(def, bb, bb2) | + not defOccursInBlock(def, bb2, _) and + not ssaDefReachesEndOfBlock(bb2, def, _) + ) + ) +} + +/** + * NB: If this predicate is exposed, it should be cached. + * + * Same as `lastRefRedef`, but ignores uncertain reads. + */ +pragma[nomagic] +predicate lastRefNoUncertainReads(Definition def, BasicBlock bb, int i) { + lastRef(def, bb, i) and + not variableRead(bb, i, def.getSourceVariable(), false) + or + exists(BasicBlock bb0, int i0 | + lastRef(def, bb0, i0) and + adjacentDefReachesUncertainRead(def, bb, i, bb0, i0) + ) +} + +/** A static single assignment (SSA) definition. */ +class Definition extends TDefinition { + /** Gets the source variable underlying this SSA definition. */ + SourceVariable getSourceVariable() { this.definesAt(result, _, _) } + + /** + * Holds if this SSA definition defines `v` at index `i` in basic block `bb`. + * Phi nodes are considered to be at index `-1`, while normal variable writes + * are at the index of the control flow node they wrap. + */ + final predicate definesAt(SourceVariable v, BasicBlock bb, int i) { + this = TWriteDef(v, bb, i) + or + this = TPhiNode(v, bb) and i = -1 + } + + /** Gets the basic block to which this SSA definition belongs. */ + final BasicBlock getBasicBlock() { this.definesAt(_, result, _) } + + /** Gets a textual representation of this SSA definition. */ + string toString() { none() } +} + +/** An SSA definition that corresponds to a write. */ +class WriteDefinition extends Definition, TWriteDef { + private SourceVariable v; + private BasicBlock bb; + private int i; + + WriteDefinition() { this = TWriteDef(v, bb, i) } + + override string toString() { result = "WriteDef" } +} + +/** A phi node. */ +class PhiNode extends Definition, TPhiNode { + override string toString() { result = "Phi" } +} + +/** + * An SSA definition that represents an uncertain update of the underlying + * source variable. + */ +class UncertainWriteDefinition extends WriteDefinition { + UncertainWriteDefinition() { + exists(SourceVariable v, BasicBlock bb, int i | + this.definesAt(v, bb, i) and + variableWrite(bb, i, v, false) + ) + } +} diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/basessa/SsaImplSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/basessa/SsaImplSpecific.qll new file mode 100644 index 00000000000..f095926e2a4 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/basessa/SsaImplSpecific.qll @@ -0,0 +1,51 @@ +/** Provides the C# specific parameters for `SsaImplCommon.qll`. */ + +private import csharp +private import AssignableDefinitions + +class BasicBlock = ControlFlow::BasicBlock; + +BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() } + +BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() } + +class ExitBasicBlock = ControlFlow::BasicBlocks::ExitBlock; + +pragma[noinline] +private Callable getAnAssigningCallable(LocalScopeVariable v) { + result = any(AssignableDefinition def | def.getTarget() = v).getEnclosingCallable() +} + +class SourceVariable extends LocalScopeVariable { + SourceVariable() { not getAnAssigningCallable(this) != getAnAssigningCallable(this) } +} + +/** + * Holds if the `i`th node of basic block `bb` is assignable definition `def`, + * targeting local scope variable `v`. + */ +predicate definitionAt(AssignableDefinition def, BasicBlock bb, int i, SourceVariable v) { + bb.getNode(i) = def.getAControlFlowNode() and + v = def.getTarget() and + // In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x` + not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | first = def | + second.getAssignment() = first.getAssignment() and + second.getEvaluationOrder() > first.getEvaluationOrder() and + second.getTarget() = v + ) +} + +predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) { + exists(AssignableDefinition def | + definitionAt(def, bb, i, v) and + if def.isCertain() then certain = true else certain = false + ) +} + +predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) { + exists(AssignableRead read | + read.getAControlFlowNode() = bb.getNode(i) and + read.getTarget() = v and + certain = true + ) +} diff --git a/csharp/ql/src/semmle/code/csharp/dispatch/Dispatch.qll b/csharp/ql/src/semmle/code/csharp/dispatch/Dispatch.qll index fd460adf508..1e0eaaf8017 100644 --- a/csharp/ql/src/semmle/code/csharp/dispatch/Dispatch.qll +++ b/csharp/ql/src/semmle/code/csharp/dispatch/Dispatch.qll @@ -312,8 +312,13 @@ private module Internal { 1 < strictcount(this.getADynamicTarget().getUnboundDeclaration()) and c = this.getCall().getEnclosingCallable().getUnboundDeclaration() and ( - exists(AssignableDefinitions::ImplicitParameterDefinition pdef, Parameter p | - this.getQualifier() = BaseSsa::getARead(pdef, p) and + exists( + BaseSsa::Definition def, AssignableDefinitions::ImplicitParameterDefinition pdef, + Parameter p + | + pdef = def.getDefinition() and + p = pdef.getTarget() and + this.getQualifier() = def.getARead() and p.getPosition() = i and c.getAParameter() = p and not p.isParams() diff --git a/csharp/ql/test/experimental/Security Features/Serialization/test0.cs b/csharp/ql/test/experimental/Security Features/Serialization/test0.cs index 30d266203fa..2efcb4facf3 100644 --- a/csharp/ql/test/experimental/Security Features/Serialization/test0.cs +++ b/csharp/ql/test/experimental/Security Features/Serialization/test0.cs @@ -1,4 +1,4 @@ -// semmle-extractor-options: /r:System.Data.Common.dll /r:System.Runtime.WindowsRuntime.dll /r:System.Xml.XmlSerializer.dll /r:System.Runtime.Serialization.Xml.dll /r:System.Runtime.Serialization.Xml.dll /r:System.Collections.dll /r:System.Private.Xml.dll /r:System.Private.DataContractSerialization.dll /r:System.Runtime.Extensions.dll /r:System.ComponentModel.TypeConverter.dll /r:System.Xml.ReaderWriter.dll /r:System.IO.FileSystem.dll +// semmle-extractor-options: /r:System.Data.Common.dll /r:System.Xml.XmlSerializer.dll /r:System.Runtime.Serialization.Xml.dll /r:System.Runtime.Serialization.Xml.dll /r:System.Collections.dll /r:System.Private.Xml.dll /r:System.Private.DataContractSerialization.dll /r:System.Runtime.Extensions.dll /r:System.ComponentModel.TypeConverter.dll /r:System.Xml.ReaderWriter.dll /r:System.IO.FileSystem.dll using System; using System.Data; @@ -19,9 +19,9 @@ namespace DataSetSerializationTest } } - /* + /* * TODO: I cannot use DataContract on a QL unit test - * + * [DataContract(Name = "Customer", Namespace = "http://www.contoso.com")] public class PatternDataContractSerializer : XmlObjectSerializer { diff --git a/csharp/ql/test/library-tests/assemblies/compilation.expected b/csharp/ql/test/library-tests/assemblies/compilation.expected index 5075507382c..9fbb90c90ef 100644 --- a/csharp/ql/test/library-tests/assemblies/compilation.expected +++ b/csharp/ql/test/library-tests/assemblies/compilation.expected @@ -1,9 +1,9 @@ | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | no compilation | | Locations, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | has compilation | | System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | no compilation | -| System.Console, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | no compilation | +| System.Console, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | no compilation | | System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | no compilation | -| System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e | no compilation | -| System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | no compilation | -| System.Runtime.Extensions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | no compilation | +| System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e | no compilation | +| System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | no compilation | +| System.Runtime.Extensions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | no compilation | | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | no compilation | diff --git a/csharp/ql/test/library-tests/cil/attributes/attribute.expected b/csharp/ql/test/library-tests/cil/attributes/attribute.expected index 6ec0b072ec8..7ced55cab61 100644 --- a/csharp/ql/test/library-tests/cil/attributes/attribute.expected +++ b/csharp/ql/test/library-tests/cil/attributes/attribute.expected @@ -1,24 +1,29 @@ attrNoArg | !0 System.ReadOnlySpan`1.Enumerator.Current | [IsReadOnlyAttribute(...)] | | !0 System.ReadOnlySpan`1.Item | [IsReadOnlyAttribute(...)] | -| <>f__AnonymousType0`1 | [CompilerGeneratedAttribute(...)] | | | [CompilerGeneratedAttribute(...)] | -| Internal.Runtime.InteropServices.ComponentActivator.<>c__DisplayClass6_0 | [CompilerGeneratedAttribute(...)] | -| Interop.Sys.<>c__DisplayClass39_0 | [CompilerGeneratedAttribute(...)] | +| Internal.Runtime.InteropServices.ComponentActivator.<>c__DisplayClass7_0 | [CompilerGeneratedAttribute(...)] | +| Interop.HostPolicy.corehost_error_writer_fn | [UnmanagedFunctionPointerAttribute(...)] | +| Interop.HostPolicy.corehost_resolve_component_dependencies_result_fn | [UnmanagedFunctionPointerAttribute(...)] | +| Interop.PollEvents | [FlagsAttribute(...)] | +| Interop.Sys.<>c__DisplayClass37_0 | [CompilerGeneratedAttribute(...)] | | Interop.Sys.FileStatusFlags | [FlagsAttribute(...)] | | Interop.Sys.OpenFlags | [FlagsAttribute(...)] | -| Interop.Sys.PollEvents | [FlagsAttribute(...)] | | InteropErrorExtensions | [ExtensionAttribute(...)] | | Microsoft.CodeAnalysis.EmbeddedAttribute | [CompilerGeneratedAttribute(...)] | | Microsoft.CodeAnalysis.EmbeddedAttribute | [EmbeddedAttribute(...)] | -| Microsoft.Reflection.ReflectionExtensions | [ExtensionAttribute(...)] | | Microsoft.Win32.SafeHandles.SafeFileHandle.<>c | [CompilerGeneratedAttribute(...)] | | Microsoft.Win32.SafeHandles.SafeFileHandle.k__BackingField | [CompilerGeneratedAttribute(...)] | +| Microsoft.Win32.SafeHandles.SafeFileHandle.t_lastCloseErrorInfo | [ThreadStaticAttribute(...)] | | System.AppContext.FirstChanceException | [CompilerGeneratedAttribute(...)] | | System.AppContext.ProcessExit | [CompilerGeneratedAttribute(...)] | | System.AppContext.UnhandledException | [CompilerGeneratedAttribute(...)] | | System.AppDomain.DomainUnload | [CompilerGeneratedAttribute(...)] | | System.AppDomain.ReflectionOnlyAssemblyResolve | [CompilerGeneratedAttribute(...)] | +| System.ApplicationId.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.ApplicationId.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.ApplicationId.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.ApplicationId.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.ArgIterator | [IsByRefLikeAttribute(...)] | | System.Array.SorterGenericArray | [IsReadOnlyAttribute(...)] | | System.Array.SorterObjectArray | [IsReadOnlyAttribute(...)] | @@ -35,30 +40,19 @@ attrNoArg | System.ByReference`1 | [IsByRefLikeAttribute(...)] | | System.ByReference`1 | [IsReadOnlyAttribute(...)] | | System.ByReference`1 | [NonVersionableAttribute(...)] | -| System.Collections.Concurrent.ConcurrentQueueSegment`1.Slot.Item | [AllowNullAttribute(...)] | -| System.Collections.Concurrent.ConcurrentQueueSegment`1.Slot.Item | [MaybeNullAttribute(...)] | | System.Collections.Concurrent.ConcurrentQueue`1.d__26 | [CompilerGeneratedAttribute(...)] | +| System.Collections.Generic.BitHelper | [IsByRefLikeAttribute(...)] | | System.Collections.Generic.Comparer`1.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Collections.Generic.Dictionary`2.KeyCollection.Enumerator._currentKey | [AllowNullAttribute(...)] | -| System.Collections.Generic.Dictionary`2.KeyCollection.Enumerator._currentKey | [MaybeNullAttribute(...)] | -| System.Collections.Generic.Dictionary`2.ValueCollection.Enumerator._currentValue | [AllowNullAttribute(...)] | -| System.Collections.Generic.Dictionary`2.ValueCollection.Enumerator._currentValue | [MaybeNullAttribute(...)] | | System.Collections.Generic.EqualityComparer`1.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Collections.Generic.KeyValuePair`2 | [IsReadOnlyAttribute(...)] | -| System.Collections.Generic.List`1.Enumerator._current | [AllowNullAttribute(...)] | -| System.Collections.Generic.List`1.Enumerator._current | [MaybeNullAttribute(...)] | -| System.Collections.Generic.NonRandomizedStringEqualityComparer.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Collections.Generic.ReferenceEqualityComparer.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Collections.Generic.ValueListBuilder`1 | [IsByRefLikeAttribute(...)] | -| System.CommonlyUsedGenericInstantiations.d__4`1 | [CompilerGeneratedAttribute(...)] | -| System.CommonlyUsedGenericInstantiations.d__5 | [CompilerGeneratedAttribute(...)] | -| System.CommonlyUsedGenericInstantiations.d__3`1 | [CompilerGeneratedAttribute(...)] | | System.ComponentModel.EditorBrowsableAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Console.<>c | [CompilerGeneratedAttribute(...)] | | System.ConsoleCancelEventArgs.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.ConsoleKeyInfo | [IsReadOnlyAttribute(...)] | | System.ConsoleModifiers | [FlagsAttribute(...)] | | System.ConsolePal.<>c | [CompilerGeneratedAttribute(...)] | -| System.ConsolePal.<>c__DisplayClass115_0 | [CompilerGeneratedAttribute(...)] | +| System.ConsolePal.<>c__DisplayClass112_0 | [CompilerGeneratedAttribute(...)] | | System.ConsolePal.ControlCHandlerRegistrar.<>c | [CompilerGeneratedAttribute(...)] | | System.ConsolePal.TerminalFormatStrings.<>c | [CompilerGeneratedAttribute(...)] | | System.Convert | [ExtensionAttribute(...)] | @@ -68,15 +62,35 @@ attrNoArg | System.DateTimeResult | [IsByRefLikeAttribute(...)] | | System.DefaultBinder.Primitives | [FlagsAttribute(...)] | | System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes | [FlagsAttribute(...)] | +| System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.MemberNotNullAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.CodeAnalysis.NotNullWhenAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.ConditionalAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Debug.t_indentLevel | [ThreadStaticAttribute(...)] | | System.Diagnostics.DebuggableAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -93,6 +107,7 @@ attrNoArg | System.Diagnostics.DebuggerVisualizerAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.DebuggerVisualizerAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.StackFrameHelper.t_reentrancy | [ThreadStaticAttribute(...)] | +| System.Diagnostics.Tracing.CounterGroup.<>c__DisplayClass21_0 | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.CounterPayload | [EventDataAttribute(...)] | | System.Diagnostics.Tracing.CounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.CounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -139,11 +154,11 @@ attrNoArg | System.Diagnostics.Tracing.EventListener._EventSourceCreated | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventManifestOptions | [FlagsAttribute(...)] | | System.Diagnostics.Tracing.EventPayload.d__17 | [CompilerGeneratedAttribute(...)] | -| System.Diagnostics.Tracing.EventPipeController.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventPipeEventDispatcher.EventListenerSubscription.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventPipeEventDispatcher.EventListenerSubscription.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventProvider.<>c | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventProvider.s_returnCode | [ThreadStaticAttribute(...)] | +| System.Diagnostics.Tracing.EventSource.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventSource.m_EventSourceExceptionRecurenceCount | [ThreadStaticAttribute(...)] | | System.Diagnostics.Tracing.EventSource.m_EventSourceInDecodeObject | [ThreadStaticAttribute(...)] | | System.Diagnostics.Tracing.EventSourceAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -207,17 +222,14 @@ attrNoArg | System.Diagnostics.Tracing.TraceLoggingTypeInfo.threadCache | [ThreadStaticAttribute(...)] | | System.Diagnostics.Tracing.XplatEventLogger.<>c | [CompilerGeneratedAttribute(...)] | | System.Environment.<>c | [CompilerGeneratedAttribute(...)] | +| System.Environment.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Exception.DispatchState | [IsReadOnlyAttribute(...)] | -| System.GC.MemoryLoadChangeNotification | [IsReadOnlyAttribute(...)] | -| System.GC.MemoryLoadChangeNotification.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.GC.MemoryLoadChangeNotification.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.GC.MemoryLoadChangeNotification.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.GCGenerationInfo | [IsReadOnlyAttribute(...)] | +| System.GCGenerationInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.GCGenerationInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.GCGenerationInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.GCGenerationInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.GCMemoryInfo | [IsReadOnlyAttribute(...)] | -| System.GCMemoryInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.GCMemoryInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.GCMemoryInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.GCMemoryInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.GCMemoryInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Globalization.CalendarData.<>c | [CompilerGeneratedAttribute(...)] | | System.Globalization.CompareOptions | [FlagsAttribute(...)] | | System.Globalization.CultureInfo.s_currentThreadCulture | [ThreadStaticAttribute(...)] | @@ -230,6 +242,7 @@ attrNoArg | System.Globalization.GlobalizationMode.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Globalization.MonthNameStyles | [FlagsAttribute(...)] | | System.Globalization.NumberStyles | [FlagsAttribute(...)] | +| System.Globalization.OrdinalCasing | [ExtensionAttribute(...)] | | System.Globalization.TextInfo.ToLowerConversion | [IsReadOnlyAttribute(...)] | | System.Globalization.TextInfo.ToUpperConversion | [IsReadOnlyAttribute(...)] | | System.Globalization.TimeSpanParse.StringParser | [IsByRefLikeAttribute(...)] | @@ -240,6 +253,15 @@ attrNoArg | System.Globalization.TimeSpanParse.TimeSpanTokenizer | [IsByRefLikeAttribute(...)] | | System.Globalization.TimeSpanStyles | [FlagsAttribute(...)] | | System.Guid | [NonVersionableAttribute(...)] | +| System.Half | [IsReadOnlyAttribute(...)] | +| System.HexConverter.<>c | [CompilerGeneratedAttribute(...)] | +| System.IO.BufferedStream.<>c | [CompilerGeneratedAttribute(...)] | +| System.IO.BufferedStream.d__70 | [CompilerGeneratedAttribute(...)] | +| System.IO.BufferedStream.d__35 | [CompilerGeneratedAttribute(...)] | +| System.IO.BufferedStream.d__38 | [CompilerGeneratedAttribute(...)] | +| System.IO.BufferedStream.d__42 | [CompilerGeneratedAttribute(...)] | +| System.IO.BufferedStream.d__51 | [CompilerGeneratedAttribute(...)] | +| System.IO.BufferedStream.d__62 | [CompilerGeneratedAttribute(...)] | | System.IO.FileAccess | [FlagsAttribute(...)] | | System.IO.FileAttributes | [FlagsAttribute(...)] | | System.IO.FileLoadException.k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -250,10 +272,10 @@ attrNoArg | System.IO.FileShare | [FlagsAttribute(...)] | | System.IO.FileStream.<>c | [CompilerGeneratedAttribute(...)] | | System.IO.Path.<>c | [CompilerGeneratedAttribute(...)] | -| System.IO.Stream.<g__FinishReadAsync\|47_0>d | [CompilerGeneratedAttribute(...)] | +| System.IO.Stream.<g__FinishReadAsync\|46_0>d | [CompilerGeneratedAttribute(...)] | | System.IO.Stream.<>c | [CompilerGeneratedAttribute(...)] | -| System.IO.Stream.d__30 | [CompilerGeneratedAttribute(...)] | -| System.IO.Stream.d__60 | [CompilerGeneratedAttribute(...)] | +| System.IO.Stream.d__29 | [CompilerGeneratedAttribute(...)] | +| System.IO.Stream.d__59 | [CompilerGeneratedAttribute(...)] | | System.IO.Stream.SynchronousAsyncResult.<>c | [CompilerGeneratedAttribute(...)] | | System.IO.StreamReader.d__64 | [CompilerGeneratedAttribute(...)] | | System.IO.StreamReader.d__67 | [CompilerGeneratedAttribute(...)] | @@ -298,8 +320,19 @@ attrNoArg | System.Number.FloatingPointInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Number.FloatingPointInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Number.NumberBuffer | [IsByRefLikeAttribute(...)] | +| System.Numerics.Matrix3x2 | [IntrinsicAttribute(...)] | +| System.Numerics.Matrix4x4 | [IntrinsicAttribute(...)] | +| System.Numerics.Plane | [IntrinsicAttribute(...)] | +| System.Numerics.Quaternion | [IntrinsicAttribute(...)] | | System.Numerics.Vector | [IntrinsicAttribute(...)] | +| System.Numerics.Vector2 | [IntrinsicAttribute(...)] | +| System.Numerics.Vector3 | [IntrinsicAttribute(...)] | +| System.Numerics.Vector4 | [IntrinsicAttribute(...)] | | System.Numerics.Vector`1 | [IntrinsicAttribute(...)] | +| System.ObsoleteAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.ObsoleteAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.ObsoleteAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.ObsoleteAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.ParamsArray | [IsReadOnlyAttribute(...)] | | System.ParseFlags | [FlagsAttribute(...)] | | System.Progress`1.ProgressChanged | [CompilerGeneratedAttribute(...)] | @@ -404,14 +437,14 @@ attrNoArg | System.Resources.NeutralResourcesLanguageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Resources.ResourceFallbackManager.d__5 | [CompilerGeneratedAttribute(...)] | | System.Resources.ResourceReader.<>c | [CompilerGeneratedAttribute(...)] | -| System.Resources.ResourceReader.<>c__DisplayClass49_0`1 | [CompilerGeneratedAttribute(...)] | +| System.Resources.ResourceReader.<>c__DisplayClass7_0`1 | [CompilerGeneratedAttribute(...)] | | System.Resources.SatelliteContractVersionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.AssemblyTargetedPatchBandAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.AccessedThroughPropertyAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.AsyncMethodBuilderAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.StateMachine | [AllowNullAttribute(...)] | -| System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.StateMachine | [MaybeNullAttribute(...)] | | System.Runtime.CompilerServices.CallerArgumentExpressionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.CastHelpers.CastCacheEntry._source | [NativeIntegerAttribute(...)] | +| System.Runtime.CompilerServices.CastHelpers.CastCacheEntry._targetAndResult | [NativeIntegerAttribute(...)] | | System.Runtime.CompilerServices.CompilationRelaxations | [FlagsAttribute(...)] | | System.Runtime.CompilerServices.CompilationRelaxationsAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.ConditionalWeakTable`2.<>c | [CompilerGeneratedAttribute(...)] | @@ -434,19 +467,30 @@ attrNoArg | System.Runtime.CompilerServices.FixedBufferAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.InternalsVisibleToAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.InternalsVisibleToAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.CompilerServices.JitHelpers | [ExtensionAttribute(...)] | +| System.Runtime.CompilerServices.IsUnmanagedAttribute | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.IsUnmanagedAttribute | [EmbeddedAttribute(...)] | | System.Runtime.CompilerServices.MethodImplAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.MethodImplOptions | [FlagsAttribute(...)] | +| System.Runtime.CompilerServices.NativeIntegerAttribute | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.NativeIntegerAttribute | [EmbeddedAttribute(...)] | | System.Runtime.CompilerServices.NullableAttribute | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.NullableAttribute | [EmbeddedAttribute(...)] | | System.Runtime.CompilerServices.NullableContextAttribute | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.NullableContextAttribute | [EmbeddedAttribute(...)] | | System.Runtime.CompilerServices.NullablePublicOnlyAttribute | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.NullablePublicOnlyAttribute | [EmbeddedAttribute(...)] | +| System.Runtime.CompilerServices.ObjectHandleOnStack | [IsByRefLikeAttribute(...)] | +| System.Runtime.CompilerServices.QCallAssembly | [IsByRefLikeAttribute(...)] | +| System.Runtime.CompilerServices.QCallModule | [IsByRefLikeAttribute(...)] | +| System.Runtime.CompilerServices.QCallTypeHandle | [IsByRefLikeAttribute(...)] | | System.Runtime.CompilerServices.ReferenceAssemblyAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.RuntimeCompatibilityAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.RuntimeHelpers | [ExtensionAttribute(...)] | +| System.Runtime.CompilerServices.StackCrawlMarkHandle | [IsByRefLikeAttribute(...)] | | System.Runtime.CompilerServices.StateMachineAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.StringHandleOnStack | [IsByRefLikeAttribute(...)] | | System.Runtime.CompilerServices.StrongBox`1.Value | [MaybeNullAttribute(...)] | +| System.Runtime.CompilerServices.SwitchExpressionException.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.TaskAwaiter | [IsReadOnlyAttribute(...)] | | System.Runtime.CompilerServices.TaskAwaiter.<>c | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.TaskAwaiter`1 | [IsReadOnlyAttribute(...)] | @@ -478,6 +522,8 @@ attrNoArg | System.Runtime.InteropServices.ComTypes.TYPEFLAGS | [FlagsAttribute(...)] | | System.Runtime.InteropServices.ComTypes.VARFLAGS | [FlagsAttribute(...)] | | System.Runtime.InteropServices.ComVisibleAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.CreateComInterfaceFlags | [FlagsAttribute(...)] | +| System.Runtime.InteropServices.CreateObjectFlags | [FlagsAttribute(...)] | | System.Runtime.InteropServices.CurrencyWrapper.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.DefaultCharSetAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -494,14 +540,17 @@ attrNoArg | System.Runtime.InteropServices.LCIDConversionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.Marshal.<>c | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.MarshalAsAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.MemoryMarshal.d__3`1 | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.MemoryMarshal.d__15`1 | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.ProgIdAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.SafeBuffer._numBytes | [NativeIntegerAttribute(...)] | | System.Runtime.InteropServices.StructLayoutAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.TypeIdentifierAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.TypeIdentifierAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.UnknownWrapper.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.VariantWrapper.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Intrinsics.Arm.Crc32 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.Arm.Crc32.Arm64 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.Vector64 | [ExtensionAttribute(...)] | | System.Runtime.Intrinsics.Vector64DebugView`1 | [IsReadOnlyAttribute(...)] | | System.Runtime.Intrinsics.Vector64`1 | [IntrinsicAttribute(...)] | @@ -515,33 +564,40 @@ attrNoArg | System.Runtime.Intrinsics.Vector256`1 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.Vector256`1 | [IsReadOnlyAttribute(...)] | | System.Runtime.Intrinsics.X86.Aes | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Aes.X64 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Avx | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Avx2 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Avx2.X64 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Avx.X64 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Bmi1 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Bmi1.X64 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Bmi2 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Bmi2.X64 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Fma | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Fma.X64 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Lzcnt | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Lzcnt.X64 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Pclmulqdq | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Pclmulqdq.X64 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Popcnt | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Popcnt.X64 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Sse | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Sse2 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Sse2.X64 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Sse3 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Sse3.X64 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Sse41 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Sse41.X64 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Sse42 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Sse42.X64 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Sse.X64 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.X86.Ssse3 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Ssse3.X64 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.X86Base | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.X86Base.X64 | [IntrinsicAttribute(...)] | | System.Runtime.Loader.AssemblyDependencyResolver.<>c__DisplayClass6_0 | [CompilerGeneratedAttribute(...)] | -| System.Runtime.Loader.AssemblyDependencyResolver.corehost_error_writer_fn | [UnmanagedFunctionPointerAttribute(...)] | -| System.Runtime.Loader.AssemblyDependencyResolver.corehost_resolve_component_dependencies_result_fn | [UnmanagedFunctionPointerAttribute(...)] | -| System.Runtime.Loader.AssemblyLoadContext.d__88 | [CompilerGeneratedAttribute(...)] | -| System.Runtime.Loader.AssemblyLoadContext.d__58 | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Loader.AssemblyLoadContext.d__83 | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Loader.AssemblyLoadContext.d__53 | [CompilerGeneratedAttribute(...)] | | System.Runtime.Loader.AssemblyLoadContext.AssemblyLoad | [CompilerGeneratedAttribute(...)] | | System.Runtime.Loader.AssemblyLoadContext.AssemblyResolve | [CompilerGeneratedAttribute(...)] | | System.Runtime.Loader.AssemblyLoadContext.ResourceResolve | [CompilerGeneratedAttribute(...)] | @@ -560,9 +616,35 @@ attrNoArg | System.Runtime.Serialization.StreamingContext | [IsReadOnlyAttribute(...)] | | System.Runtime.Serialization.StreamingContextStates | [FlagsAttribute(...)] | | System.Runtime.TargetedPatchingOptOutAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Versioning.ComponentGuaranteesAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Versioning.ComponentGuaranteesOptions | [FlagsAttribute(...)] | +| System.Runtime.Versioning.OSPlatformAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Versioning.ResourceConsumptionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Versioning.ResourceConsumptionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Versioning.ResourceExposureAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Versioning.ResourceScope | [FlagsAttribute(...)] | +| System.Runtime.Versioning.SxSRequirements | [FlagsAttribute(...)] | | System.RuntimeArgumentHandle | [IsByRefLikeAttribute(...)] | | System.RuntimeType.RuntimeTypeCache.Filter | [IsReadOnlyAttribute(...)] | | System.Security.AllowPartiallyTrustedCallersAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.Permissions.SecurityAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.Permissions.SecurityAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.Permissions.SecurityPermissionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.Permissions.SecurityPermissionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.Permissions.SecurityPermissionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.Permissions.SecurityPermissionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.Permissions.SecurityPermissionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.Permissions.SecurityPermissionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.Permissions.SecurityPermissionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.Permissions.SecurityPermissionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.Permissions.SecurityPermissionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.Permissions.SecurityPermissionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.Permissions.SecurityPermissionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.Permissions.SecurityPermissionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.Permissions.SecurityPermissionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.Permissions.SecurityPermissionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.Permissions.SecurityPermissionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.Permissions.SecurityPermissionFlag | [FlagsAttribute(...)] | | System.Security.SecurityCriticalAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Security.SecurityElement.<>c | [CompilerGeneratedAttribute(...)] | | System.Security.SecurityException.k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -583,13 +665,13 @@ attrNoArg | System.Span`1 | [IsReadOnlyAttribute(...)] | | System.Span`1 | [NonVersionableAttribute(...)] | | System.Span`1.Enumerator | [IsByRefLikeAttribute(...)] | +| System.StringNormalizationExtensions | [ExtensionAttribute(...)] | | System.StringSplitOptions | [FlagsAttribute(...)] | | System.TermInfo.ParameterizedStrings.FormatParam | [IsReadOnlyAttribute(...)] | | System.TermInfo.ParameterizedStrings.t_cachedOneElementArgsArray | [ThreadStaticAttribute(...)] | | System.TermInfo.ParameterizedStrings.t_cachedStack | [ThreadStaticAttribute(...)] | | System.TermInfo.ParameterizedStrings.t_cachedTwoElementArgsArray | [ThreadStaticAttribute(...)] | | System.Text.CodePageDataItem.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Text.CodePageDataItem.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Text.CodePageDataItem.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Text.CodePageDataItem.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Text.CodePageDataItem.k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -599,10 +681,19 @@ attrNoArg | System.Text.EncodingInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Text.EncodingInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Text.EncodingInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Text.EncodingInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Text.Latin1Encoding.<>c | [CompilerGeneratedAttribute(...)] | | System.Text.Rune | [IsReadOnlyAttribute(...)] | | System.Text.SpanRuneEnumerator | [IsByRefLikeAttribute(...)] | | System.Text.StringBuilderCache.t_cachedInstance | [ThreadStaticAttribute(...)] | | System.Text.StringOrCharArray | [IsReadOnlyAttribute(...)] | +| System.Text.TranscodingStream.<g__DisposeAsyncCore\|30_0>d | [CompilerGeneratedAttribute(...)] | +| System.Text.TranscodingStream.<g__ReadAsyncCore\|41_0>d | [CompilerGeneratedAttribute(...)] | +| System.Text.TranscodingStream.<g__WriteAsyncCore\|50_0>d | [CompilerGeneratedAttribute(...)] | +| System.Text.TrimType | [FlagsAttribute(...)] | +| System.Text.Unicode.TextSegmentationUtility.Processor`1 | [IsByRefLikeAttribute(...)] | +| System.Text.Unicode.TextSegmentationUtility.Processor`1.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Text.Unicode.TextSegmentationUtility.Processor`1.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Text.ValueStringBuilder | [IsByRefLikeAttribute(...)] | | System.Threading.AsyncLocalValueChangedArgs`1 | [IsReadOnlyAttribute(...)] | | System.Threading.AsyncLocalValueChangedArgs`1.k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -615,6 +706,7 @@ attrNoArg | System.Threading.CancellationTokenSource.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.CancellationTokenSource.CallbackNode.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.CancellationTokenSource.LinkedNCancellationTokenSource.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.ProcessorIdCache.t_currentProcessorIdCache | [ThreadStaticAttribute(...)] | | System.Threading.QueueUserWorkItemCallback.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.ReaderWriterLockSlim.WaiterStates | [FlagsAttribute(...)] | | System.Threading.ReaderWriterLockSlim.t_rwc | [ThreadStaticAttribute(...)] | @@ -629,14 +721,11 @@ attrNoArg | System.Threading.Tasks.SingleProducerSingleConsumerQueue`1.d__11 | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1._result | [AllowNullAttribute(...)] | -| System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1._result | [MaybeNullAttribute(...)] | | System.Threading.Tasks.Sources.ValueTaskSourceOnCompletedFlags | [FlagsAttribute(...)] | | System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation.<>c__DisplayClass6_0 | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.SynchronizationContextTaskScheduler.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.Task.<>c | [CompilerGeneratedAttribute(...)] | -| System.Threading.Tasks.Task.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.Task.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.Task.DelayPromise.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.Task.DelayPromiseWithCancellation.<>c | [CompilerGeneratedAttribute(...)] | @@ -651,13 +740,11 @@ attrNoArg | System.Threading.Tasks.TaskFactory`1.<>c__DisplayClass38_0`1 | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.TaskFactory`1.<>c__DisplayClass41_0`2 | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.TaskFactory`1.<>c__DisplayClass44_0`3 | [CompilerGeneratedAttribute(...)] | -| System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.m_thisRef | [AllowNullAttribute(...)] | -| System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.m_thisRef | [MaybeNullAttribute(...)] | | System.Threading.Tasks.TaskScheduler.UnobservedTaskException | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.TaskSchedulerAwaitTaskContinuation.<>c | [CompilerGeneratedAttribute(...)] | -| System.Threading.Tasks.TaskToApm.<>c__DisplayClass3_0 | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.TaskToApm.TaskAsyncResult.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.TaskToApm.TaskAsyncResult.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.Task`1.TaskWhenAnyCast.<>c | [CompilerGeneratedAttribute(...)] | -| System.Threading.Tasks.Task`1.m_result | [MaybeNullAttribute(...)] | | System.Threading.Tasks.ThreadPoolTaskScheduler.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.ThreadPoolTaskScheduler.d__6 | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.UnwrapPromise`1.<>c | [CompilerGeneratedAttribute(...)] | @@ -665,17 +752,13 @@ attrNoArg | System.Threading.Tasks.ValueTask.ValueTaskSourceAsTask.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.ValueTask`1 | [IsReadOnlyAttribute(...)] | | System.Threading.Tasks.ValueTask`1.ValueTaskSourceAsTask.<>c | [CompilerGeneratedAttribute(...)] | -| System.Threading.Tasks.ValueTask`1._result | [AllowNullAttribute(...)] | -| System.Threading.Thread.t_currentProcessorIdCache | [ThreadStaticAttribute(...)] | | System.Threading.Thread.t_currentThread | [ThreadStaticAttribute(...)] | | System.Threading.ThreadHandle | [IsReadOnlyAttribute(...)] | -| System.Threading.ThreadLocal`1.LinkedSlot._value | [AllowNullAttribute(...)] | -| System.Threading.ThreadLocal`1.LinkedSlot._value | [MaybeNullAttribute(...)] | | System.Threading.ThreadLocal`1.ts_finalizationHelper | [ThreadStaticAttribute(...)] | | System.Threading.ThreadLocal`1.ts_slotArray | [ThreadStaticAttribute(...)] | -| System.Threading.ThreadPool.d__51 | [CompilerGeneratedAttribute(...)] | -| System.Threading.ThreadPool.d__50 | [CompilerGeneratedAttribute(...)] | -| System.Threading.ThreadPoolGlobals.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.ThreadPool.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.ThreadPool.d__52 | [CompilerGeneratedAttribute(...)] | +| System.Threading.ThreadPool.d__51 | [CompilerGeneratedAttribute(...)] | | System.Threading.ThreadPoolWorkQueueThreadLocals.threadLocals | [ThreadStaticAttribute(...)] | | System.Threading.ThreadState | [FlagsAttribute(...)] | | System.Threading.TimerQueue.k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -686,7 +769,7 @@ attrNoArg | System.ThrowHelper | [StackTraceHiddenAttribute(...)] | | System.TimeSpan | [IsReadOnlyAttribute(...)] | | System.TimeZoneInfo.<>c | [CompilerGeneratedAttribute(...)] | -| System.TimeZoneInfo.<>c__DisplayClass125_0 | [CompilerGeneratedAttribute(...)] | +| System.TimeZoneInfo.<>c__DisplayClass124_0 | [CompilerGeneratedAttribute(...)] | | System.TimeZoneInfo.TransitionTime | [IsReadOnlyAttribute(...)] | | System.TimeZoneInfoOptions | [FlagsAttribute(...)] | | System.TupleExtensions | [ExtensionAttribute(...)] | @@ -694,6 +777,7 @@ attrNoArg | System.TypedReference | [IsByRefLikeAttribute(...)] | | System.TypedReference | [NonVersionableAttribute(...)] | | System.UIntPtr | [IsReadOnlyAttribute(...)] | +| System.UIntPtr System.Runtime.InteropServices.SafeBuffer.Uninitialized | [NativeIntegerAttribute(...)] | | System.UIntPtr.Zero | [IntrinsicAttribute(...)] | | System.__DTString | [IsByRefLikeAttribute(...)] | | bool | [IsReadOnlyAttribute(...)] | @@ -719,19 +803,34 @@ attrArgNamed | System.Buffers.ArrayPoolEventSource | [EventSourceAttribute(...)] | Name | System.Buffers.ArrayPoolEventSource | | System.CLSCompliantAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.CLSCompliantAttribute | [AttributeUsageAttribute(...)] | Inherited | True | +| System.CodeDom.Compiler.GeneratedCodeAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.CodeDom.Compiler.GeneratedCodeAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Collections.KeyValuePairs | [DebuggerDisplayAttribute(...)] | Name | [{_key}] | +| System.ContextStaticAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Diagnostics.CodeAnalysis.AllowNullAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Diagnostics.CodeAnalysis.DisallowNullAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Diagnostics.CodeAnalysis.MaybeNullAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.CodeAnalysis.MemberNotNullAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Diagnostics.CodeAnalysis.MemberNotNullAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Diagnostics.CodeAnalysis.NotNullAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | | System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Diagnostics.CodeAnalysis.NotNullWhenAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Diagnostics.ConditionalAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | | System.Diagnostics.Contracts.ContractAbbreviatorAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Diagnostics.Contracts.ContractArgumentValidatorAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | @@ -827,15 +926,21 @@ attrArgNamed | System.Runtime.CompilerServices.IteratorStateMachineAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.CompilerServices.IteratorStateMachineAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.CompilerServices.MethodImplAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.ModuleInitializerAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.NativeIntegerAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.CompilerServices.NativeIntegerAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.CompilerServices.NullableAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.CompilerServices.NullableAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.CompilerServices.NullableContextAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.CompilerServices.NullableContextAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.CompilerServices.NullablePublicOnlyAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.CompilerServices.NullablePublicOnlyAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.PreserveBaseOverridesAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.CompilerServices.PreserveBaseOverridesAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.CompilerServices.ReferenceAssemblyAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.CompilerServices.RuntimeCompatibilityAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.CompilerServices.RuntimeCompatibilityAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.SkipLocalsInitAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.CompilerServices.StateMachineAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.CompilerServices.StateMachineAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.CompilerServices.StringFreezingAttribute | [AttributeUsageAttribute(...)] | Inherited | False | @@ -845,12 +950,22 @@ attrArgNamed | System.Runtime.CompilerServices.TypeForwardedFromAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.CompilerServices.TypeForwardedToAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | | System.Runtime.CompilerServices.TypeForwardedToAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.ConstrainedExecution.Cer | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0004 | +| System.Runtime.ConstrainedExecution.Cer | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | +| System.Runtime.ConstrainedExecution.Consistency | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0004 | +| System.Runtime.ConstrainedExecution.Consistency | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | | System.Runtime.ConstrainedExecution.PrePrepareMethodAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.ConstrainedExecution.PrePrepareMethodAttribute | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0004 | +| System.Runtime.ConstrainedExecution.PrePrepareMethodAttribute | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | | System.Runtime.ConstrainedExecution.ReliabilityContractAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.ConstrainedExecution.ReliabilityContractAttribute | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0004 | +| System.Runtime.ConstrainedExecution.ReliabilityContractAttribute | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | | System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.InteropServices.AllowReversePInvokeCallsAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.InteropServices.AllowReversePInvokeCallsAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.AllowReversePInvokeCallsAttribute | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0003 | +| System.Runtime.InteropServices.AllowReversePInvokeCallsAttribute | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | | System.Runtime.InteropServices.BestFitMappingAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.InteropServices.ClassInterfaceAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.InteropServices.CoClassAttribute | [AttributeUsageAttribute(...)] | Inherited | False | @@ -863,6 +978,8 @@ attrArgNamed | System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.InteropServices.DispIdAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.InteropServices.DllImportAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.DynamicInterfaceCastableImplementationAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.InteropServices.DynamicInterfaceCastableImplementationAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.InteropServices.FieldOffsetAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.InteropServices.GuidAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.InteropServices.InAttribute | [AttributeUsageAttribute(...)] | Inherited | False | @@ -874,8 +991,10 @@ attrArgNamed | System.Runtime.InteropServices.PreserveSigAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.InteropServices.ProgIdAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.InteropServices.StructLayoutAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.SuppressGCTransitionAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.InteropServices.TypeIdentifierAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.InteropServices.TypeIdentifierAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.Serialization.OnDeserializedAttribute | [AttributeUsageAttribute(...)] | Inherited | False | @@ -885,12 +1004,48 @@ attrArgNamed | System.Runtime.Serialization.OptionalFieldAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.TargetedPatchingOptOutAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.TargetedPatchingOptOutAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.Versioning.ComponentGuaranteesAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.Versioning.ComponentGuaranteesAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.Versioning.NonVersionableAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.Versioning.NonVersionableAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.Versioning.ResourceConsumptionAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.Versioning.ResourceExposureAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.Versioning.SupportedOSPlatformAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Runtime.Versioning.SupportedOSPlatformAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.Versioning.TargetFrameworkAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.Versioning.TargetFrameworkAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.Versioning.TargetPlatformAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.Versioning.TargetPlatformAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.Versioning.UnsupportedOSPlatformAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Runtime.Versioning.UnsupportedOSPlatformAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Security.AllowPartiallyTrustedCallersAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Security.AllowPartiallyTrustedCallersAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Security.IPermission | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0003 | +| System.Security.IPermission | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | +| System.Security.IStackWalk | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0003 | +| System.Security.IStackWalk | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | +| System.Security.PermissionSet | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0003 | +| System.Security.PermissionSet | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | +| System.Security.PermissionSet System.AppDomain.PermissionSet | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0003 | +| System.Security.PermissionSet System.AppDomain.PermissionSet | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | +| System.Security.Permissions.CodeAccessSecurityAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Security.Permissions.CodeAccessSecurityAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Security.Permissions.CodeAccessSecurityAttribute | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0003 | +| System.Security.Permissions.CodeAccessSecurityAttribute | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | +| System.Security.Permissions.PermissionState | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0003 | +| System.Security.Permissions.PermissionState | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | +| System.Security.Permissions.SecurityAction | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0003 | +| System.Security.Permissions.SecurityAction | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | +| System.Security.Permissions.SecurityAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Security.Permissions.SecurityAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Security.Permissions.SecurityAttribute | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0003 | +| System.Security.Permissions.SecurityAttribute | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | +| System.Security.Permissions.SecurityPermissionAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Security.Permissions.SecurityPermissionAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Security.Permissions.SecurityPermissionAttribute | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0003 | +| System.Security.Permissions.SecurityPermissionAttribute | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | +| System.Security.Permissions.SecurityPermissionFlag | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0003 | +| System.Security.Permissions.SecurityPermissionFlag | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | | System.Security.SecurityCriticalAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Security.SecurityCriticalAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Security.SecurityRulesAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | @@ -905,22 +1060,33 @@ attrArgNamed | System.Security.UnverifiableCodeAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | | System.Security.UnverifiableCodeAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.SerializableAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Text.Encoding System.Text.Encoding.UTF7 | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0001 | +| System.Text.Encoding System.Text.Encoding.UTF7 | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | | System.Text.Encoding._isReadOnly | [OptionalFieldAttribute(...)] | VersionAdded | 2 | | System.ThreadStaticAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Threading.Tasks.TplEventSource | [EventSourceAttribute(...)] | Guid | 2e5dba47-a3d2-4d16-8ee0-6671ffdcd7b5 | -| System.Threading.Tasks.TplEventSource | [EventSourceAttribute(...)] | LocalizationResources | System.Private.CoreLib.Resources.Strings | +| System.Threading.Tasks.TplEventSource | [EventSourceAttribute(...)] | LocalizationResources | System.Private.CoreLib.Strings | | System.Threading.Tasks.TplEventSource | [EventSourceAttribute(...)] | Name | System.Threading.Tasks.TplEventSource | +| bool System.Reflection.Assembly.GlobalAssemblyCache | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0005 | +| bool System.Reflection.Assembly.GlobalAssemblyCache | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | +| bool System.Reflection.Emit.AssemblyBuilder.GlobalAssemblyCache | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0005 | +| bool System.Reflection.Emit.AssemblyBuilder.GlobalAssemblyCache | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | +| bool System.Reflection.RuntimeAssembly.GlobalAssemblyCache | [ObsoleteAttribute(...)] | DiagnosticId | SYSLIB0005 | +| bool System.Reflection.RuntimeAssembly.GlobalAssemblyCache | [ObsoleteAttribute(...)] | UrlFormat | https://aka.ms/dotnet-warnings/{0} | attrArgPositional | !0 System.ArraySegment`1.Enumerator.Current | [NullableAttribute(...)] | 0 | 1 | | !0 System.Collections.Generic.Dictionary`2.KeyCollection.Enumerator.Current | [NullableAttribute(...)] | 0 | 1 | +| !0 System.Collections.Generic.HashSet`1.Enumerator.Current | [NullableAttribute(...)] | 0 | 1 | | !0 System.Collections.Generic.IAsyncEnumerator`1.Current | [NullableAttribute(...)] | 0 | 1 | | !0 System.Collections.Generic.IEnumerator`1.Current | [NullableAttribute(...)] | 0 | 1 | | !0 System.Collections.Generic.List`1.Enumerator.Current | [NullableAttribute(...)] | 0 | 1 | | !0 System.Lazy`1.Value | [DebuggerBrowsableAttribute(...)] | 0 | 0 | +| !0 System.Lazy`1.ValueForDebugDisplay | [NullableAttribute(...)] | 0 | 2 | | !0 System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.Enumerator.Current | [NullableAttribute(...)] | 0 | 1 | | !0 System.Threading.Tasks.Task`1.Result | [DebuggerBrowsableAttribute(...)] | 0 | 0 | | !0 System.Threading.Tasks.ValueTask`1.Result | [DebuggerBrowsableAttribute(...)] | 0 | 0 | | !0 System.Threading.ThreadLocal`1.Value | [DebuggerBrowsableAttribute(...)] | 0 | 0 | +| !0 System.Threading.ThreadLocal`1.ValueForDebugDisplay | [NullableAttribute(...)] | 0 | 2 | | !0 System.Tuple`1.Item1 | [NullableAttribute(...)] | 0 | 1 | | !0 System.Tuple`2.Item1 | [NullableAttribute(...)] | 0 | 1 | | !0[] System.ArraySegment`1.Array | [NullableAttribute(...)] | 0 | [2,1] | @@ -932,12 +1098,19 @@ attrArgPositional | !1 System.Collections.Generic.Dictionary`2.ValueCollection.Enumerator.Current | [NullableAttribute(...)] | 0 | 1 | | !1 System.Tuple`2.Item2 | [NullableAttribute(...)] | 0 | 1 | | !1[] System.Collections.Generic.DictionaryValueCollectionDebugView`2.Items | [DebuggerBrowsableAttribute(...)] | 0 | 3 | -| <>f__AnonymousType0`1.i__Field | [DebuggerBrowsableAttribute(...)] | 0 | 0 | | Internal.Runtime.CompilerServices.Unsafe | [CLSCompliantAttribute(...)] | 0 | False | | Internal.Runtime.CompilerServices.Unsafe | [NullableAttribute(...)] | 0 | 0 | | Internal.Runtime.CompilerServices.Unsafe | [NullableContextAttribute(...)] | 0 | 1 | -| Internal.Threading.Tasks.AsyncCausalitySupport | [NullableAttribute(...)] | 0 | 0 | -| Internal.Threading.Tasks.AsyncCausalitySupport | [NullableContextAttribute(...)] | 0 | 1 | +| Internal.Runtime.InteropServices.ComActivationContext | [NullableAttribute(...)] | 0 | 0 | +| Internal.Runtime.InteropServices.ComActivationContext | [NullableContextAttribute(...)] | 0 | 1 | +| Internal.Runtime.InteropServices.ComActivationContextInternal | [CLSCompliantAttribute(...)] | 0 | False | +| Internal.Runtime.InteropServices.IClassFactory | [ComVisibleAttribute(...)] | 0 | False | +| Internal.Runtime.InteropServices.IClassFactory | [GuidAttribute(...)] | 0 | 00000001-0000-0000-C000-000000000046 | +| Internal.Runtime.InteropServices.IClassFactory | [InterfaceTypeAttribute(...)] | 0 | 1 | +| Internal.Runtime.InteropServices.IClassFactory | [NullableContextAttribute(...)] | 0 | 2 | +| Internal.Runtime.InteropServices.IClassFactory2 | [ComVisibleAttribute(...)] | 0 | False | +| Internal.Runtime.InteropServices.IClassFactory2 | [GuidAttribute(...)] | 0 | B196B28F-BAB4-101A-B69C-00AA00341D07 | +| Internal.Runtime.InteropServices.IClassFactory2 | [InterfaceTypeAttribute(...)] | 0 | 1 | | Interop.Sys.MountPointFound | [UnmanagedFunctionPointerAttribute(...)] | 0 | 2 | | System.AccessViolationException | [NullableAttribute(...)] | 0 | 0 | | System.AccessViolationException | [NullableContextAttribute(...)] | 0 | 2 | @@ -979,15 +1152,26 @@ attrArgPositional | System.AppContext | [NullableContextAttribute(...)] | 0 | 2 | | System.AppContext.FirstChanceException | [NullableAttribute(...)] | 0 | [2,1] | | System.AppDomain | [NullableAttribute(...)] | 0 | 0 | -| System.AppDomain | [NullableContextAttribute(...)] | 0 | 2 | -| System.AppDomain System.AppDomain.CurrentDomain | [NullableAttribute(...)] | 0 | 1 | +| System.AppDomain | [NullableContextAttribute(...)] | 0 | 1 | +| System.AppDomain.AssemblyLoad | [NullableAttribute(...)] | 0 | 2 | +| System.AppDomain.AssemblyResolve | [NullableAttribute(...)] | 0 | 2 | +| System.AppDomain.DomainUnload | [NullableAttribute(...)] | 0 | 2 | | System.AppDomain.FirstChanceException | [NullableAttribute(...)] | 0 | [2,1] | +| System.AppDomain.ProcessExit | [NullableAttribute(...)] | 0 | 2 | +| System.AppDomain.ReflectionOnlyAssemblyResolve | [NullableAttribute(...)] | 0 | 2 | +| System.AppDomain.ResourceResolve | [NullableAttribute(...)] | 0 | 2 | +| System.AppDomain.TypeResolve | [NullableAttribute(...)] | 0 | 2 | +| System.AppDomain.UnhandledException | [NullableAttribute(...)] | 0 | 2 | | System.AppDomainSetup | [NullableAttribute(...)] | 0 | 0 | | System.AppDomainSetup | [NullableContextAttribute(...)] | 0 | 2 | -| System.AppDomainSetup System.AppDomain.SetupInformation | [NullableAttribute(...)] | 0 | 1 | +| System.AppDomainUnloadedException | [NullableAttribute(...)] | 0 | 0 | +| System.AppDomainUnloadedException | [NullableContextAttribute(...)] | 0 | 2 | +| System.AppDomainUnloadedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.ApplicationException | [NullableAttribute(...)] | 0 | 0 | | System.ApplicationException | [NullableContextAttribute(...)] | 0 | 2 | | System.ApplicationException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ApplicationId | [NullableAttribute(...)] | 0 | 0 | +| System.ApplicationId | [NullableContextAttribute(...)] | 0 | 1 | | System.ArgumentException | [NullableAttribute(...)] | 0 | 0 | | System.ArgumentException | [NullableContextAttribute(...)] | 0 | 2 | | System.ArgumentException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | @@ -1035,6 +1219,11 @@ attrArgPositional | System.CannotUnloadAppDomainException | [NullableAttribute(...)] | 0 | 0 | | System.CannotUnloadAppDomainException | [NullableContextAttribute(...)] | 0 | 2 | | System.CannotUnloadAppDomainException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.CodeDom.Compiler.GeneratedCodeAttribute | [AttributeUsageAttribute(...)] | 0 | 32767 | +| System.CodeDom.Compiler.GeneratedCodeAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.CodeDom.Compiler.GeneratedCodeAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.CodeDom.Compiler.IndentedTextWriter | [NullableAttribute(...)] | 0 | 0 | +| System.CodeDom.Compiler.IndentedTextWriter | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.ArrayList | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | | System.Collections.ArrayList | [DebuggerTypeProxyAttribute(...)] | 0 | System.Collections.ArrayList.ArrayListDebugView | | System.Collections.ArrayList | [DefaultMemberAttribute(...)] | 0 | Item | @@ -1066,6 +1255,8 @@ attrArgPositional | System.Collections.EmptyReadOnlyDictionaryInternal | [DefaultMemberAttribute(...)] | 0 | Item | | System.Collections.Generic.ArraySortHelper`1 | [TypeDependencyAttribute(...)] | 0 | System.Collections.Generic.GenericArraySortHelper`1 | | System.Collections.Generic.ArraySortHelper`2 | [TypeDependencyAttribute(...)] | 0 | System.Collections.Generic.GenericArraySortHelper`2 | +| System.Collections.Generic.BitHelper | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Collections.Generic.BitHelper | [ObsoleteAttribute(...)] | 1 | True | | System.Collections.Generic.ByteEqualityComparer | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Collections.Generic.Comparer`1 | [NullableAttribute(...)] | 0 | 0 | | System.Collections.Generic.Comparer`1 | [NullableContextAttribute(...)] | 0 | 1 | @@ -1092,18 +1283,24 @@ attrArgPositional | System.Collections.Generic.EqualityComparer`1 | [TypeDependencyAttribute(...)] | 0 | System.Collections.Generic.ObjectEqualityComparer`1 | | System.Collections.Generic.EqualityComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Collections.Generic.GenericComparer`1 | [NullableAttribute(...)] | 0 | [0,1] | -| System.Collections.Generic.GenericComparer`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.GenericComparer`1 | [NullableContextAttribute(...)] | 0 | 2 | | System.Collections.Generic.GenericComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Collections.Generic.GenericEqualityComparer`1 | [NullableAttribute(...)] | 0 | [0,1] | +| System.Collections.Generic.GenericEqualityComparer`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Generic.GenericEqualityComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Generic.HashSet`1 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.Generic.HashSet`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.Collections.Generic.ICollectionDebugView`1 | +| System.Collections.Generic.HashSet`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Collections.Generic.HashSet`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.HashSet`1 | [TypeForwardedFromAttribute(...)] | 0 | System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Generic.HashSet`1.Enumerator | [NullableContextAttribute(...)] | 0 | 0 | | System.Collections.Generic.IAsyncEnumerable`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Generic.ICollection`1 | [NullableContextAttribute(...)] | 0 | 1 | -| System.Collections.Generic.IComparer`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.IComparer`1 | [NullableContextAttribute(...)] | 0 | 2 | | System.Collections.Generic.IDictionary System.Diagnostics.Tracing.EventCommandEventArgs.Arguments | [NullableAttribute(...)] | 0 | [2,1,2] | | System.Collections.Generic.IDictionary`2 | [DefaultMemberAttribute(...)] | 0 | Item | | System.Collections.Generic.IDictionary`2 | [NullableContextAttribute(...)] | 0 | 1 | -| System.Collections.Generic.IEqualityComparer System.Collections.Generic.NonRandomizedStringEqualityComparer.Default | [NullableAttribute(...)] | 0 | [1,2] | -| System.Collections.Generic.IEqualityComparer`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.IEqualityComparer`1 | [NullableContextAttribute(...)] | 0 | 2 | | System.Collections.Generic.IList System.Runtime.CompilerServices.TupleElementNamesAttribute.TransformNames | [NullableAttribute(...)] | 0 | [1,2] | | System.Collections.Generic.IList`1 | [DefaultMemberAttribute(...)] | 0 | Item | | System.Collections.Generic.IList`1 | [NullableContextAttribute(...)] | 0 | 1 | @@ -1111,6 +1308,7 @@ attrArgPositional | System.Collections.Generic.IReadOnlyDictionary`2 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Generic.IReadOnlyList`1 | [DefaultMemberAttribute(...)] | 0 | Item | | System.Collections.Generic.IReadOnlyList`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.IReadOnlySet`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Generic.ISet`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Generic.KeyNotFoundException | [NullableAttribute(...)] | 0 | 0 | | System.Collections.Generic.KeyNotFoundException | [NullableContextAttribute(...)] | 0 | 2 | @@ -1120,6 +1318,8 @@ attrArgPositional | System.Collections.Generic.KeyValuePair`2 | [NullableAttribute(...)] | 0 | 0 | | System.Collections.Generic.KeyValuePair`2 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Generic.KeyValuePair`2 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Generic.KeyValuePair`2.key | [DebuggerBrowsableAttribute(...)] | 0 | 0 | +| System.Collections.Generic.KeyValuePair`2.value | [DebuggerBrowsableAttribute(...)] | 0 | 0 | | System.Collections.Generic.List System.Threading.ThreadLocal`1.ValuesForDebugDisplay | [NullableAttribute(...)] | 0 | [2,1] | | System.Collections.Generic.List`1 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | | System.Collections.Generic.List`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.Collections.Generic.ICollectionDebugView`1 | @@ -1128,16 +1328,15 @@ attrArgPositional | System.Collections.Generic.List`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Generic.List`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Collections.Generic.List`1.Enumerator | [NullableContextAttribute(...)] | 0 | 0 | -| System.Collections.Generic.NonRandomizedStringEqualityComparer | [NullableAttribute(...)] | 0 | [0,2] | -| System.Collections.Generic.NonRandomizedStringEqualityComparer | [NullableContextAttribute(...)] | 0 | 2 | | System.Collections.Generic.NullableComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Collections.Generic.NullableEqualityComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Collections.Generic.ObjectComparer`1 | [NullableAttribute(...)] | 0 | [0,1] | | System.Collections.Generic.ObjectComparer`1 | [NullableContextAttribute(...)] | 0 | 2 | | System.Collections.Generic.ObjectComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Collections.Generic.ObjectEqualityComparer`1 | [NullableAttribute(...)] | 0 | [0,1] | -| System.Collections.Generic.ObjectEqualityComparer`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.ObjectEqualityComparer`1 | [NullableContextAttribute(...)] | 0 | 2 | | System.Collections.Generic.ObjectEqualityComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Generic.ReferenceEqualityComparer System.Collections.Generic.ReferenceEqualityComparer.Instance | [NullableAttribute(...)] | 0 | 1 | | System.Collections.Generic.ValueListBuilder`1 | [DefaultMemberAttribute(...)] | 0 | Item | | System.Collections.Generic.ValueListBuilder`1 | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | | System.Collections.Generic.ValueListBuilder`1 | [ObsoleteAttribute(...)] | 1 | True | @@ -1159,7 +1358,6 @@ attrArgPositional | System.Collections.IEnumerable | [ComVisibleAttribute(...)] | 0 | True | | System.Collections.IEnumerable | [GuidAttribute(...)] | 0 | 496B0ABE-CDEE-11d3-88E8-00902754C43A | | System.Collections.IEnumerable | [NullableContextAttribute(...)] | 0 | 1 | -| System.Collections.IEnumerator | [NullableContextAttribute(...)] | 0 | 2 | | System.Collections.IEqualityComparer | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.IEqualityComparer System.Collections.Hashtable.EqualityComparer | [NullableAttribute(...)] | 0 | 2 | | System.Collections.IHashCodeProvider | [NullableContextAttribute(...)] | 0 | 1 | @@ -1196,6 +1394,16 @@ attrArgPositional | System.ComponentModel.DefaultValueAttribute | [NullableAttribute(...)] | 0 | 0 | | System.ComponentModel.DefaultValueAttribute | [NullableContextAttribute(...)] | 0 | 2 | | System.ComponentModel.EditorBrowsableAttribute | [AttributeUsageAttribute(...)] | 0 | 6140 | +| System.Console | [NullableAttribute(...)] | 0 | 0 | +| System.Console | [NullableContextAttribute(...)] | 0 | 1 | +| System.Console.CancelKeyPress | [NullableAttribute(...)] | 0 | 2 | +| System.Console.CancelKeyPress | [UnsupportedOSPlatformAttribute(...)] | 0 | browser | +| System.ConsoleColor System.Console.BackgroundColor | [UnsupportedOSPlatformAttribute(...)] | 0 | browser | +| System.ConsoleColor System.Console.ForegroundColor | [UnsupportedOSPlatformAttribute(...)] | 0 | browser | +| System.ContextMarshalException | [NullableAttribute(...)] | 0 | 0 | +| System.ContextMarshalException | [NullableContextAttribute(...)] | 0 | 2 | +| System.ContextMarshalException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ContextStaticAttribute | [AttributeUsageAttribute(...)] | 0 | 256 | | System.Convert | [NullableAttribute(...)] | 0 | 0 | | System.Convert | [NullableContextAttribute(...)] | 0 | 2 | | System.Convert.DBNull | [NullableAttribute(...)] | 0 | 1 | @@ -1225,17 +1433,36 @@ attrArgPositional | System.Diagnostics.CodeAnalysis.DisallowNullAttribute | [AttributeUsageAttribute(...)] | 0 | 2432 | | System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | +| System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute | [AttributeUsageAttribute(...)] | 0 | 352 | +| System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute | [AttributeUsageAttribute(...)] | 0 | 27072 | +| System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute | [AttributeUsageAttribute(...)] | 0 | 749 | +| System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute | [NullableContextAttribute(...)] | 0 | 2 | | System.Diagnostics.CodeAnalysis.MaybeNullAttribute | [AttributeUsageAttribute(...)] | 0 | 10624 | | System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | +| System.Diagnostics.CodeAnalysis.MemberNotNullAttribute | [AttributeUsageAttribute(...)] | 0 | 192 | +| System.Diagnostics.CodeAnalysis.MemberNotNullAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.CodeAnalysis.MemberNotNullAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute | [AttributeUsageAttribute(...)] | 0 | 192 | +| System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Diagnostics.CodeAnalysis.NotNullAttribute | [AttributeUsageAttribute(...)] | 0 | 10624 | | System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute | [AttributeUsageAttribute(...)] | 0 | 10368 | | System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Diagnostics.CodeAnalysis.NotNullWhenAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | +| System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute | [AttributeUsageAttribute(...)] | 0 | 96 | +| System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute | [AttributeUsageAttribute(...)] | 0 | 32767 | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute | [ConditionalAttribute(...)] | 0 | CODE_ANALYSIS | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute | [AttributeUsageAttribute(...)] | 0 | 32767 | +| System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute | [NullableContextAttribute(...)] | 0 | 2 | | System.Diagnostics.ConditionalAttribute | [AttributeUsageAttribute(...)] | 0 | 68 | | System.Diagnostics.ConditionalAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.ConditionalAttribute | [NullableContextAttribute(...)] | 0 | 1 | @@ -1371,7 +1598,7 @@ attrArgPositional | System.Exception | [NullableContextAttribute(...)] | 0 | 2 | | System.Exception | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Exception.SerializeObjectState | [NullableAttribute(...)] | 0 | [2,1] | -| System.Exception[] System.Reflection.ReflectionTypeLoadException.LoaderExceptions | [NullableAttribute(...)] | 0 | 2 | +| System.Exception[] System.Reflection.ReflectionTypeLoadException.LoaderExceptions | [NullableAttribute(...)] | 0 | [1,2] | | System.ExecutionEngineException | [NullableAttribute(...)] | 0 | 0 | | System.ExecutionEngineException | [NullableContextAttribute(...)] | 0 | 2 | | System.ExecutionEngineException | [ObsoleteAttribute(...)] | 0 | This type previously indicated an unspecified fatal error in the runtime. The runtime no longer raises this exception so this type is obsolete. | @@ -1438,8 +1665,6 @@ attrArgPositional | System.Globalization.EraInfo[] System.Globalization.TaiwanLunisolarCalendar.CalEraInfo | [NullableAttribute(...)] | 0 | [2,1] | | System.Globalization.GregorianCalendar | [NullableAttribute(...)] | 0 | 0 | | System.Globalization.GregorianCalendar | [NullableContextAttribute(...)] | 0 | 1 | -| System.Globalization.HebrewCalendar | [NullableAttribute(...)] | 0 | 0 | -| System.Globalization.HebrewCalendar | [NullableContextAttribute(...)] | 0 | 1 | | System.Globalization.HijriCalendar | [NullableAttribute(...)] | 0 | 0 | | System.Globalization.HijriCalendar | [NullableContextAttribute(...)] | 0 | 1 | | System.Globalization.IdnMapping | [NullableAttribute(...)] | 0 | 0 | @@ -1492,20 +1717,23 @@ attrArgPositional | System.Guid | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.HashCode | [NullableAttribute(...)] | 0 | 0 | | System.HashCode | [NullableContextAttribute(...)] | 0 | 1 | +| System.HexConverter.<>c.<>9__4_0 | [TupleElementNamesAttribute(...)] | 0 | [Ptr,Length,casing] | | System.IAsyncResult | [NullableContextAttribute(...)] | 0 | 1 | | System.ICloneable | [NullableContextAttribute(...)] | 0 | 1 | | System.IComparable | [NullableContextAttribute(...)] | 0 | 2 | -| System.IComparable`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.IComparable`1 | [NullableContextAttribute(...)] | 0 | 2 | | System.IConvertible | [CLSCompliantAttribute(...)] | 0 | False | | System.IConvertible | [NullableContextAttribute(...)] | 0 | 2 | | System.ICustomFormatter | [NullableContextAttribute(...)] | 0 | 2 | -| System.IEquatable`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.IEquatable`1 | [NullableContextAttribute(...)] | 0 | 2 | | System.IFormatProvider | [NullableContextAttribute(...)] | 0 | 2 | | System.IFormattable | [NullableContextAttribute(...)] | 0 | 2 | | System.IO.BinaryReader | [NullableAttribute(...)] | 0 | 0 | | System.IO.BinaryReader | [NullableContextAttribute(...)] | 0 | 1 | | System.IO.BinaryWriter | [NullableAttribute(...)] | 0 | 0 | | System.IO.BinaryWriter | [NullableContextAttribute(...)] | 0 | 1 | +| System.IO.BufferedStream | [NullableAttribute(...)] | 0 | 0 | +| System.IO.BufferedStream | [NullableContextAttribute(...)] | 0 | 1 | | System.IO.DirectoryNotFoundException | [NullableAttribute(...)] | 0 | 0 | | System.IO.DirectoryNotFoundException | [NullableContextAttribute(...)] | 0 | 2 | | System.IO.DirectoryNotFoundException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | @@ -1523,6 +1751,9 @@ attrArgPositional | System.IO.IOException | [NullableAttribute(...)] | 0 | 0 | | System.IO.IOException | [NullableContextAttribute(...)] | 0 | 2 | | System.IO.IOException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.IO.InvalidDataException | [NullableAttribute(...)] | 0 | 0 | +| System.IO.InvalidDataException | [NullableContextAttribute(...)] | 0 | 2 | +| System.IO.InvalidDataException | [TypeForwardedFromAttribute(...)] | 0 | System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.IO.MemoryStream | [NullableAttribute(...)] | 0 | 0 | | System.IO.MemoryStream | [NullableContextAttribute(...)] | 0 | 1 | | System.IO.Path.<>c.<>9__37_0 | [TupleElementNamesAttribute(...)] | 0 | [First,FirstLength,Second,SecondLength,HasSeparator] | @@ -1539,8 +1770,13 @@ attrArgPositional | System.IO.StreamReader | [NullableContextAttribute(...)] | 0 | 1 | | System.IO.StreamWriter | [NullableAttribute(...)] | 0 | 0 | | System.IO.StreamWriter | [NullableContextAttribute(...)] | 0 | 1 | +| System.IO.StringReader | [NullableAttribute(...)] | 0 | 0 | +| System.IO.StringReader | [NullableContextAttribute(...)] | 0 | 1 | +| System.IO.StringWriter | [NullableAttribute(...)] | 0 | 0 | +| System.IO.StringWriter | [NullableContextAttribute(...)] | 0 | 1 | | System.IO.TextReader | [NullableAttribute(...)] | 0 | 0 | | System.IO.TextReader | [NullableContextAttribute(...)] | 0 | 1 | +| System.IO.TextReader System.Console.In | [UnsupportedOSPlatformAttribute(...)] | 0 | browser | | System.IO.TextWriter | [NullableAttribute(...)] | 0 | 0 | | System.IO.TextWriter | [NullableContextAttribute(...)] | 0 | 1 | | System.IObservable`1 | [NullableContextAttribute(...)] | 0 | 1 | @@ -1576,6 +1812,9 @@ attrArgPositional | System.Lazy`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Lazy`2 | [NullableAttribute(...)] | 0 | [0,1] | | System.Lazy`2 | [NullableContextAttribute(...)] | 0 | 1 | +| System.LoaderOptimization.DisallowBindings | [ObsoleteAttribute(...)] | 0 | This method has been deprecated. Please use Assembly.Load() instead. https://go.microsoft.com/fwlink/?linkid=14202 | +| System.LoaderOptimization.DomainMask | [ObsoleteAttribute(...)] | 0 | This method has been deprecated. Please use Assembly.Load() instead. https://go.microsoft.com/fwlink/?linkid=14202 | +| System.LoaderOptimizationAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.MTAThreadAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.MarshalByRefObject | [ClassInterfaceAttribute(...)] | 0 | 1 | | System.MarshalByRefObject | [ComVisibleAttribute(...)] | 0 | True | @@ -1612,6 +1851,8 @@ attrArgPositional | System.MulticastNotSupportedException | [NullableAttribute(...)] | 0 | 0 | | System.MulticastNotSupportedException | [NullableContextAttribute(...)] | 0 | 2 | | System.MulticastNotSupportedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Net.WebUtility | [NullableAttribute(...)] | 0 | 0 | +| System.Net.WebUtility | [NullableContextAttribute(...)] | 0 | 2 | | System.NonSerializedAttribute | [AttributeUsageAttribute(...)] | 0 | 256 | | System.NotFiniteNumberException | [NullableAttribute(...)] | 0 | 0 | | System.NotFiniteNumberException | [NullableContextAttribute(...)] | 0 | 2 | @@ -1634,6 +1875,12 @@ attrArgPositional | System.Number.DiyFp | [ObsoleteAttribute(...)] | 1 | True | | System.Number.NumberBuffer | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | | System.Number.NumberBuffer | [ObsoleteAttribute(...)] | 1 | True | +| System.Numerics.Vector2 | [NullableAttribute(...)] | 0 | 0 | +| System.Numerics.Vector2 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Numerics.Vector3 | [NullableAttribute(...)] | 0 | 0 | +| System.Numerics.Vector3 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Numerics.Vector4 | [NullableAttribute(...)] | 0 | 0 | +| System.Numerics.Vector4 | [NullableContextAttribute(...)] | 0 | 1 | | System.Numerics.Vector`1 | [DefaultMemberAttribute(...)] | 0 | Item | | System.ObjectDisposedException | [NullableAttribute(...)] | 0 | 0 | | System.ObjectDisposedException | [NullableContextAttribute(...)] | 0 | 1 | @@ -1678,10 +1925,12 @@ attrArgPositional | System.ReadOnlyMemory`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.ReadOnlySpan System.ReadOnlyMemory`1.Span | [NullableAttribute(...)] | 0 | [0,1] | | System.ReadOnlySpan System.ReadOnlySpan`1.Empty | [NullableAttribute(...)] | 0 | [0,1] | +| System.ReadOnlySpan System.Globalization.CompareInfo.HighCharTable | [NullableAttribute(...)] | 0 | 0 | | System.ReadOnlySpan System.Text.Encoding.Preamble | [NullableAttribute(...)] | 0 | 0 | | System.ReadOnlySpan System.Text.UTF32Encoding.Preamble | [NullableAttribute(...)] | 0 | 0 | | System.ReadOnlySpan System.Text.UnicodeEncoding.Preamble | [NullableAttribute(...)] | 0 | 0 | -| System.ReadOnlySpan char.CategoryForLatin1 | [NullableAttribute(...)] | 0 | 0 | +| System.ReadOnlySpan char.Latin1CharInfo | [NullableAttribute(...)] | 0 | 0 | +| System.ReadOnlySpan System.Convert.DecodingMap | [NullableAttribute(...)] | 0 | 0 | | System.ReadOnlySpan`1 | [DebuggerDisplayAttribute(...)] | 0 | {ToString(),raw} | | System.ReadOnlySpan`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.SpanDebugView`1 | | System.ReadOnlySpan`1 | [DefaultMemberAttribute(...)] | 0 | Item | @@ -1697,6 +1946,7 @@ attrArgPositional | System.Reflection.AmbiguousMatchException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Reflection.Assembly | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.Assembly | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Assembly System.ResolveEventArgs.RequestingAssembly | [NullableAttribute(...)] | 0 | 2 | | System.Reflection.Assembly.ModuleResolve | [NullableAttribute(...)] | 0 | 2 | | System.Reflection.AssemblyAlgorithmIdAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Reflection.AssemblyCompanyAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | @@ -1787,6 +2037,7 @@ attrArgPositional | System.Reflection.Emit.DynamicScope | [DefaultMemberAttribute(...)] | 0 | Item | | System.Reflection.Emit.EnumBuilder | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.Emit.EnumBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.EnumBuilder.m_typeBuilder | [DynamicallyAccessedMembersAttribute(...)] | 0 | -1 | | System.Reflection.Emit.EventBuilder | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.Emit.EventBuilder | [NullableContextAttribute(...)] | 0 | 1 | | System.Reflection.Emit.FieldBuilder | [NullableAttribute(...)] | 0 | 0 | @@ -1800,6 +2051,7 @@ attrArgPositional | System.Reflection.Emit.LocalBuilder | [NullableContextAttribute(...)] | 0 | 1 | | System.Reflection.Emit.MethodBuilder | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.Emit.MethodBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.MethodBuilder.m_containingType | [DynamicallyAccessedMembersAttribute(...)] | 0 | -1 | | System.Reflection.Emit.ModuleBuilder | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.Emit.ModuleBuilder | [NullableContextAttribute(...)] | 0 | 1 | | System.Reflection.Emit.OpCode | [NullableAttribute(...)] | 0 | 0 | @@ -1814,6 +2066,9 @@ attrArgPositional | System.Reflection.Emit.SignatureHelper | [NullableContextAttribute(...)] | 0 | 1 | | System.Reflection.Emit.TypeBuilder | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.Emit.TypeBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.TypeBuilder.m_bakedRuntimeType | [DynamicallyAccessedMembersAttribute(...)] | 0 | -1 | +| System.Reflection.Emit.TypeBuilder.m_typeParent | [DynamicallyAccessedMembersAttribute(...)] | 0 | -1 | +| System.Reflection.Emit.__ExceptionInfo[] System.Reflection.Emit.ILGenerator.CurrExcStack | [NullableAttribute(...)] | 0 | [2,1] | | System.Reflection.EventInfo | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.EventInfo | [NullableContextAttribute(...)] | 0 | 2 | | System.Reflection.ExceptionHandlingClause | [NullableAttribute(...)] | 0 | 0 | @@ -1831,7 +2086,7 @@ attrArgPositional | System.Reflection.LocalVariableInfo | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.LocalVariableInfo | [NullableContextAttribute(...)] | 0 | 1 | | System.Reflection.ManifestResourceInfo | [NullableAttribute(...)] | 0 | 0 | -| System.Reflection.ManifestResourceInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.ManifestResourceInfo | [NullableContextAttribute(...)] | 0 | 2 | | System.Reflection.MemberInfo | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.MemberInfo | [NullableContextAttribute(...)] | 0 | 1 | | System.Reflection.MetadataEnumResult | [DefaultMemberAttribute(...)] | 0 | Item | @@ -1884,10 +2139,11 @@ attrArgPositional | System.Reflection.TargetParameterCountException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Reflection.TypeDelegator | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.TypeDelegator | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.TypeDelegator.typeImpl | [DynamicallyAccessedMembersAttribute(...)] | 0 | -1 | | System.Reflection.TypeInfo | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.TypeInfo | [NullableContextAttribute(...)] | 0 | 1 | | System.ResolveEventArgs | [NullableAttribute(...)] | 0 | 0 | -| System.ResolveEventArgs | [NullableContextAttribute(...)] | 0 | 2 | +| System.ResolveEventArgs | [NullableContextAttribute(...)] | 0 | 1 | | System.Resources.MissingManifestResourceException | [NullableAttribute(...)] | 0 | 0 | | System.Resources.MissingManifestResourceException | [NullableContextAttribute(...)] | 0 | 2 | | System.Resources.MissingManifestResourceException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | @@ -1900,6 +2156,7 @@ attrArgPositional | System.Resources.ResourceManager | [NullableAttribute(...)] | 0 | 0 | | System.Resources.ResourceManager | [NullableContextAttribute(...)] | 0 | 1 | | System.Resources.ResourceManager.MainAssembly | [NullableAttribute(...)] | 0 | 2 | +| System.Resources.ResourceManager._userResourceSet | [DynamicallyAccessedMembersAttribute(...)] | 0 | 7 | | System.Resources.ResourceSet | [NullableAttribute(...)] | 0 | 0 | | System.Resources.ResourceSet | [NullableContextAttribute(...)] | 0 | 1 | | System.Resources.SatelliteContractVersionAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | @@ -1937,6 +2194,7 @@ attrArgPositional | System.Runtime.CompilerServices.CallerFilePathAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | | System.Runtime.CompilerServices.CallerLineNumberAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | | System.Runtime.CompilerServices.CallerMemberNameAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | +| System.Runtime.CompilerServices.CastHelpers.CastCacheEntry | [DebuggerDisplayAttribute(...)] | 0 | Source = {_source}; Target = {_targetAndResult & ~1}; Result = {_targetAndResult & 1}; VersionNum = {_version & ((1 << 29) - 1)}; Distance = {_version >> 29}; | | System.Runtime.CompilerServices.CompilationRelaxationsAttribute | [AttributeUsageAttribute(...)] | 0 | 71 | | System.Runtime.CompilerServices.CompilerGeneratedAttribute | [AttributeUsageAttribute(...)] | 0 | 32767 | | System.Runtime.CompilerServices.CompilerGlobalScopeAttribute | [AttributeUsageAttribute(...)] | 0 | 4 | @@ -1958,6 +2216,7 @@ attrArgPositional | System.Runtime.CompilerServices.DependencyAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.DependencyAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.DisablePrivateReflectionAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.DiscardableAttribute | [AttributeUsageAttribute(...)] | 0 | 32767 | | System.Runtime.CompilerServices.EnumeratorCancellationAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | | System.Runtime.CompilerServices.ExtensionAttribute | [AttributeUsageAttribute(...)] | 0 | 69 | | System.Runtime.CompilerServices.FixedAddressValueTypeAttribute | [AttributeUsageAttribute(...)] | 0 | 256 | @@ -1977,13 +2236,25 @@ attrArgPositional | System.Runtime.CompilerServices.IntrinsicAttribute | [AttributeUsageAttribute(...)] | 0 | 364 | | System.Runtime.CompilerServices.IsByRefLikeAttribute | [AttributeUsageAttribute(...)] | 0 | 8 | | System.Runtime.CompilerServices.IsByRefLikeAttribute | [EditorBrowsableAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.IsExternalInit | [EditorBrowsableAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.IsReadOnlyAttribute | [AttributeUsageAttribute(...)] | 0 | 32767 | | System.Runtime.CompilerServices.IsReadOnlyAttribute | [EditorBrowsableAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.IteratorStateMachineAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.Runtime.CompilerServices.MethodImplAttribute | [AttributeUsageAttribute(...)] | 0 | 96 | +| System.Runtime.CompilerServices.ModuleInitializerAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | +| System.Runtime.CompilerServices.NativeIntegerAttribute | [AttributeUsageAttribute(...)] | 0 | 27524 | | System.Runtime.CompilerServices.NullableAttribute | [AttributeUsageAttribute(...)] | 0 | 27524 | -| System.Runtime.CompilerServices.NullableContextAttribute | [AttributeUsageAttribute(...)] | 0 | 5198 | +| System.Runtime.CompilerServices.NullableContextAttribute | [AttributeUsageAttribute(...)] | 0 | 5196 | | System.Runtime.CompilerServices.NullablePublicOnlyAttribute | [AttributeUsageAttribute(...)] | 0 | 2 | +| System.Runtime.CompilerServices.ObjectHandleOnStack | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Runtime.CompilerServices.ObjectHandleOnStack | [ObsoleteAttribute(...)] | 1 | True | +| System.Runtime.CompilerServices.PreserveBaseOverridesAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | +| System.Runtime.CompilerServices.QCallAssembly | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Runtime.CompilerServices.QCallAssembly | [ObsoleteAttribute(...)] | 1 | True | +| System.Runtime.CompilerServices.QCallModule | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Runtime.CompilerServices.QCallModule | [ObsoleteAttribute(...)] | 1 | True | +| System.Runtime.CompilerServices.QCallTypeHandle | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Runtime.CompilerServices.QCallTypeHandle | [ObsoleteAttribute(...)] | 1 | True | | System.Runtime.CompilerServices.ReferenceAssemblyAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.ReferenceAssemblyAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.ReferenceAssemblyAttribute | [NullableContextAttribute(...)] | 0 | 2 | @@ -1997,13 +2268,21 @@ attrArgPositional | System.Runtime.CompilerServices.RuntimeWrappedException | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.RuntimeWrappedException | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.RuntimeWrappedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Runtime.CompilerServices.SkipLocalsInitAttribute | [AttributeUsageAttribute(...)] | 0 | 1774 | | System.Runtime.CompilerServices.SpecialNameAttribute | [AttributeUsageAttribute(...)] | 0 | 972 | +| System.Runtime.CompilerServices.StackCrawlMarkHandle | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Runtime.CompilerServices.StackCrawlMarkHandle | [ObsoleteAttribute(...)] | 1 | True | | System.Runtime.CompilerServices.StateMachineAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.Runtime.CompilerServices.StateMachineAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.StateMachineAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.StringFreezingAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.StringHandleOnStack | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Runtime.CompilerServices.StringHandleOnStack | [ObsoleteAttribute(...)] | 1 | True | | System.Runtime.CompilerServices.StrongBox`1.Value | [NullableAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.SuppressIldasmAttribute | [AttributeUsageAttribute(...)] | 0 | 3 | +| System.Runtime.CompilerServices.SwitchExpressionException | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.SwitchExpressionException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.CompilerServices.SwitchExpressionException | [TypeForwardedFromAttribute(...)] | 0 | System.Runtime.Extensions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | | System.Runtime.CompilerServices.TupleElementNamesAttribute | [AttributeUsageAttribute(...)] | 0 | 11148 | | System.Runtime.CompilerServices.TupleElementNamesAttribute | [CLSCompliantAttribute(...)] | 0 | False | | System.Runtime.CompilerServices.TypeDependencyAttribute | [AttributeUsageAttribute(...)] | 0 | 1036 | @@ -2014,14 +2293,19 @@ attrArgPositional | System.Runtime.CompilerServices.TypeForwardedToAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.TypeForwardedToAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.UnsafeValueTypeAttribute | [AttributeUsageAttribute(...)] | 0 | 8 | +| System.Runtime.ConstrainedExecution.Cer | [ObsoleteAttribute(...)] | 0 | The Constrained Execution Region (CER) feature is not supported. | +| System.Runtime.ConstrainedExecution.Consistency | [ObsoleteAttribute(...)] | 0 | The Constrained Execution Region (CER) feature is not supported. | | System.Runtime.ConstrainedExecution.PrePrepareMethodAttribute | [AttributeUsageAttribute(...)] | 0 | 96 | +| System.Runtime.ConstrainedExecution.PrePrepareMethodAttribute | [ObsoleteAttribute(...)] | 0 | The Constrained Execution Region (CER) feature is not supported. | | System.Runtime.ConstrainedExecution.ReliabilityContractAttribute | [AttributeUsageAttribute(...)] | 0 | 1133 | +| System.Runtime.ConstrainedExecution.ReliabilityContractAttribute | [ObsoleteAttribute(...)] | 0 | The Constrained Execution Region (CER) feature is not supported. | | System.Runtime.ExceptionServices.ExceptionDispatchInfo | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.ExceptionServices.ExceptionDispatchInfo | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.Runtime.InteropServices.AllowReversePInvokeCallsAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | +| System.Runtime.InteropServices.AllowReversePInvokeCallsAttribute | [ObsoleteAttribute(...)] | 0 | Code Access Security is not supported or honored by the runtime. | | System.Runtime.InteropServices.ArrayWithOffset | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.ArrayWithOffset | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.InteropServices.BStrWrapper | [NullableAttribute(...)] | 0 | 0 | @@ -2042,6 +2326,7 @@ attrArgPositional | System.Runtime.InteropServices.ComEventInterfaceAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComEventsHelper | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.ComEventsHelper | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComEventsHelper | [SupportedOSPlatformAttribute(...)] | 0 | windows | | System.Runtime.InteropServices.ComImportAttribute | [AttributeUsageAttribute(...)] | 0 | 1028 | | System.Runtime.InteropServices.ComSourceInterfacesAttribute | [AttributeUsageAttribute(...)] | 0 | 4 | | System.Runtime.InteropServices.ComSourceInterfacesAttribute | [NullableAttribute(...)] | 0 | 0 | @@ -2074,6 +2359,7 @@ attrArgPositional | System.Runtime.InteropServices.ComTypes.IEnumVARIANT | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IEnumVARIANT | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IEnumerable | [GuidAttribute(...)] | 0 | 496B0ABE-CDEE-11d3-88E8-00902754C43A | +| System.Runtime.InteropServices.ComTypes.IEnumerator | [GuidAttribute(...)] | 0 | 496B0ABF-CDEE-11d3-88E8-00902754C43A | | System.Runtime.InteropServices.ComTypes.IMoniker | [GuidAttribute(...)] | 0 | 0000000f-0000-0000-C000-000000000046 | | System.Runtime.InteropServices.ComTypes.IMoniker | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IMoniker | [NullableContextAttribute(...)] | 0 | 1 | @@ -2104,6 +2390,12 @@ attrArgPositional | System.Runtime.InteropServices.ComTypes.STATSTG.pwcsName | [NullableAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.VARDESC.lpstrSchema | [NullableAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComVisibleAttribute | [AttributeUsageAttribute(...)] | 0 | 5597 | +| System.Runtime.InteropServices.ComWrappers | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.InteropServices.ComWrappers | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.ComWrappers | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComWrappers | [SupportedOSPlatformAttribute(...)] | 0 | windows | +| System.Runtime.InteropServices.ComWrappers.ComInterfaceDispatch | [NullableContextAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.ComWrappers.ComInterfaceEntry | [NullableContextAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.DefaultCharSetAttribute | [AttributeUsageAttribute(...)] | 0 | 2 | | System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute | [AttributeUsageAttribute(...)] | 0 | 65 | | System.Runtime.InteropServices.DefaultParameterValueAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | @@ -2112,10 +2404,12 @@ attrArgPositional | System.Runtime.InteropServices.DispIdAttribute | [AttributeUsageAttribute(...)] | 0 | 960 | | System.Runtime.InteropServices.DispatchWrapper | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.DispatchWrapper | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.DispatchWrapper | [SupportedOSPlatformAttribute(...)] | 0 | windows | | System.Runtime.InteropServices.DllImportAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.Runtime.InteropServices.DllImportAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.DllImportAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.DllImportAttribute.EntryPoint | [NullableAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.DynamicInterfaceCastableImplementationAttribute | [AttributeUsageAttribute(...)] | 0 | 1024 | | System.Runtime.InteropServices.ErrorWrapper | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.ErrorWrapper | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.Expando.IExpando | [GuidAttribute(...)] | 0 | AFBF15E6-C37C-11d2-B88E-00A0C9B471B8 | @@ -2150,8 +2444,6 @@ attrArgPositional | System.Runtime.InteropServices.MarshalDirectiveException | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.MarshalDirectiveException | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.InteropServices.MarshalDirectiveException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | -| System.Runtime.InteropServices.NativeCallableAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | -| System.Runtime.InteropServices.NativeCallableAttribute.EntryPoint | [NullableAttribute(...)] | 0 | 2 | | System.Runtime.InteropServices.NativeLibrary | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.NativeLibrary | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.OptionalAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | @@ -2172,19 +2464,26 @@ attrArgPositional | System.Runtime.InteropServices.SafeHandle System.Threading.ThreadPoolBoundHandle.Handle | [NullableAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.StructLayoutAttribute | [AttributeUsageAttribute(...)] | 0 | 12 | | System.Runtime.InteropServices.StructLayoutAttribute System.Type.StructLayoutAttribute | [NullableAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.SuppressGCTransitionAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.Runtime.InteropServices.TypeIdentifierAttribute | [AttributeUsageAttribute(...)] | 0 | 5144 | | System.Runtime.InteropServices.TypeIdentifierAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.TypeIdentifierAttribute | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.InteropServices.UnknownWrapper | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.UnknownWrapper | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | +| System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute.CallConvs | [NullableAttribute(...)] | 0 | [2,1] | +| System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute.EntryPoint | [NullableAttribute(...)] | 0 | 2 | | System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute | [AttributeUsageAttribute(...)] | 0 | 4096 | | System.Runtime.InteropServices.VariantWrapper | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.VariantWrapper | [NullableContextAttribute(...)] | 0 | 2 | -| System.Runtime.Intrinsics.Arm.Arm64.Aes | [CLSCompliantAttribute(...)] | 0 | False | -| System.Runtime.Intrinsics.Arm.Arm64.Base | [CLSCompliantAttribute(...)] | 0 | False | -| System.Runtime.Intrinsics.Arm.Arm64.Sha1 | [CLSCompliantAttribute(...)] | 0 | False | -| System.Runtime.Intrinsics.Arm.Arm64.Sha256 | [CLSCompliantAttribute(...)] | 0 | False | -| System.Runtime.Intrinsics.Arm.Arm64.Simd | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.Arm.AdvSimd | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.Arm.Aes | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.Arm.ArmBase | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.Arm.Crc32 | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.Arm.Dp | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.Arm.Rdm | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.Arm.Sha1 | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.Arm.Sha256 | [CLSCompliantAttribute(...)] | 0 | False | | System.Runtime.Intrinsics.Vector64`1 | [DebuggerDisplayAttribute(...)] | 0 | {DisplayString,nq} | | System.Runtime.Intrinsics.Vector64`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.Runtime.Intrinsics.Vector64DebugView`1 | | System.Runtime.Intrinsics.Vector128`1 | [DebuggerDisplayAttribute(...)] | 0 | {DisplayString,nq} | @@ -2250,10 +2549,22 @@ attrArgPositional | System.Runtime.TargetedPatchingOptOutAttribute | [AttributeUsageAttribute(...)] | 0 | 96 | | System.Runtime.TargetedPatchingOptOutAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.TargetedPatchingOptOutAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.Versioning.ComponentGuaranteesAttribute | [AttributeUsageAttribute(...)] | 0 | 5887 | +| System.Runtime.Versioning.FrameworkName | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.Versioning.FrameworkName | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.Versioning.NonVersionableAttribute | [AttributeUsageAttribute(...)] | 0 | 108 | +| System.Runtime.Versioning.OSPlatformAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.Versioning.OSPlatformAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.Versioning.ResourceConsumptionAttribute | [AttributeUsageAttribute(...)] | 0 | 224 | +| System.Runtime.Versioning.ResourceConsumptionAttribute | [ConditionalAttribute(...)] | 0 | RESOURCE_ANNOTATION_WORK | +| System.Runtime.Versioning.ResourceExposureAttribute | [AttributeUsageAttribute(...)] | 0 | 480 | +| System.Runtime.Versioning.ResourceExposureAttribute | [ConditionalAttribute(...)] | 0 | RESOURCE_ANNOTATION_WORK | +| System.Runtime.Versioning.SupportedOSPlatformAttribute | [AttributeUsageAttribute(...)] | 0 | 1023 | | System.Runtime.Versioning.TargetFrameworkAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Runtime.Versioning.TargetFrameworkAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.Versioning.TargetFrameworkAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.Versioning.TargetPlatformAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | +| System.Runtime.Versioning.UnsupportedOSPlatformAttribute | [AttributeUsageAttribute(...)] | 0 | 1023 | | System.RuntimeType.ListBuilder`1 | [DefaultMemberAttribute(...)] | 0 | Item | | System.RuntimeTypeHandle | [NullableAttribute(...)] | 0 | 0 | | System.RuntimeTypeHandle | [NullableContextAttribute(...)] | 0 | 2 | @@ -2263,10 +2574,22 @@ attrArgPositional | System.Security.Cryptography.CryptographicException | [NullableContextAttribute(...)] | 0 | 1 | | System.Security.Cryptography.CryptographicException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Security.IPermission | [NullableContextAttribute(...)] | 0 | 2 | +| System.Security.IPermission | [ObsoleteAttribute(...)] | 0 | Code Access Security is not supported or honored by the runtime. | | System.Security.ISecurityEncodable | [NullableContextAttribute(...)] | 0 | 1 | +| System.Security.IStackWalk | [ObsoleteAttribute(...)] | 0 | Code Access Security is not supported or honored by the runtime. | | System.Security.PermissionSet | [NullableAttribute(...)] | 0 | 0 | | System.Security.PermissionSet | [NullableContextAttribute(...)] | 0 | 2 | -| System.Security.PermissionSet System.AppDomain.PermissionSet | [NullableAttribute(...)] | 0 | 1 | +| System.Security.PermissionSet | [ObsoleteAttribute(...)] | 0 | Code Access Security is not supported or honored by the runtime. | +| System.Security.PermissionSet System.AppDomain.PermissionSet | [ObsoleteAttribute(...)] | 0 | Code Access Security is not supported or honored by the runtime. | +| System.Security.Permissions.CodeAccessSecurityAttribute | [AttributeUsageAttribute(...)] | 0 | 109 | +| System.Security.Permissions.CodeAccessSecurityAttribute | [ObsoleteAttribute(...)] | 0 | Code Access Security is not supported or honored by the runtime. | +| System.Security.Permissions.PermissionState | [ObsoleteAttribute(...)] | 0 | Code Access Security is not supported or honored by the runtime. | +| System.Security.Permissions.SecurityAction | [ObsoleteAttribute(...)] | 0 | Code Access Security is not supported or honored by the runtime. | +| System.Security.Permissions.SecurityAttribute | [AttributeUsageAttribute(...)] | 0 | 109 | +| System.Security.Permissions.SecurityAttribute | [ObsoleteAttribute(...)] | 0 | Code Access Security is not supported or honored by the runtime. | +| System.Security.Permissions.SecurityPermissionAttribute | [AttributeUsageAttribute(...)] | 0 | 109 | +| System.Security.Permissions.SecurityPermissionAttribute | [ObsoleteAttribute(...)] | 0 | Code Access Security is not supported or honored by the runtime. | +| System.Security.Permissions.SecurityPermissionFlag | [ObsoleteAttribute(...)] | 0 | Code Access Security is not supported or honored by the runtime. | | System.Security.Principal.IIdentity | [NullableContextAttribute(...)] | 0 | 2 | | System.Security.Principal.IPrincipal | [NullableContextAttribute(...)] | 0 | 2 | | System.Security.Principal.IPrincipal System.Threading.Thread.CurrentPrincipal | [NullableAttribute(...)] | 0 | 2 | @@ -2308,6 +2631,8 @@ attrArgPositional | System.StringComparer | [NullableAttribute(...)] | 0 | 0 | | System.StringComparer | [NullableContextAttribute(...)] | 0 | 1 | | System.StringComparer | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.StringNormalizationExtensions | [NullableAttribute(...)] | 0 | 0 | +| System.StringNormalizationExtensions | [NullableContextAttribute(...)] | 0 | 1 | | System.SystemException | [NullableAttribute(...)] | 0 | 0 | | System.SystemException | [NullableContextAttribute(...)] | 0 | 2 | | System.SystemException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | @@ -2333,10 +2658,15 @@ attrArgPositional | System.Text.EncoderReplacementFallback | [NullableContextAttribute(...)] | 0 | 1 | | System.Text.Encoding | [NullableAttribute(...)] | 0 | 0 | | System.Text.Encoding | [NullableContextAttribute(...)] | 0 | 1 | +| System.Text.Encoding System.Console.InputEncoding | [UnsupportedOSPlatformAttribute(...)] | 0 | browser | +| System.Text.Encoding System.Text.Encoding.UTF7 | [ObsoleteAttribute(...)] | 0 | The UTF-7 encoding is insecure and should not be used. Consider using UTF-8 instead. | | System.Text.EncodingInfo | [NullableAttribute(...)] | 0 | 0 | | System.Text.EncodingInfo | [NullableContextAttribute(...)] | 0 | 1 | | System.Text.EncodingProvider | [NullableAttribute(...)] | 0 | 0 | | System.Text.EncodingProvider | [NullableContextAttribute(...)] | 0 | 1 | +| System.Text.EncodingProvider System.Text.EncodingInfo.Provider | [NullableAttribute(...)] | 0 | 2 | +| System.Text.Latin1Encoding.<>c.<>9__29_0 | [TupleElementNamesAttribute(...)] | 0 | [encoding,bytes] | +| System.Text.Latin1Encoding.<>c.<>9__30_0 | [TupleElementNamesAttribute(...)] | 0 | [encoding,bytes,index] | | System.Text.Rune | [DebuggerDisplayAttribute(...)] | 0 | {DebuggerDisplay,nq} | | System.Text.SpanRuneEnumerator | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | | System.Text.SpanRuneEnumerator | [ObsoleteAttribute(...)] | 1 | True | @@ -2349,6 +2679,8 @@ attrArgPositional | System.Text.UTF7Encoding | [NullableContextAttribute(...)] | 0 | 1 | | System.Text.UTF32Encoding | [NullableAttribute(...)] | 0 | 0 | | System.Text.UTF32Encoding | [NullableContextAttribute(...)] | 0 | 1 | +| System.Text.Unicode.TextSegmentationUtility.Processor`1 | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Text.Unicode.TextSegmentationUtility.Processor`1 | [ObsoleteAttribute(...)] | 1 | True | | System.Text.UnicodeEncoding | [NullableAttribute(...)] | 0 | 0 | | System.Text.UnicodeEncoding | [NullableContextAttribute(...)] | 0 | 1 | | System.Text.ValueStringBuilder | [DefaultMemberAttribute(...)] | 0 | Item | @@ -2361,7 +2693,7 @@ attrArgPositional | System.Threading.ApartmentState System.Threading.Thread.ApartmentState | [ObsoleteAttribute(...)] | 0 | The ApartmentState property has been deprecated. Use GetApartmentState, SetApartmentState or TrySetApartmentState instead. | | System.Threading.ApartmentState System.Threading.Thread.ApartmentState | [ObsoleteAttribute(...)] | 1 | False | | System.Threading.AsyncLocalValueChangedArgs`1 | [NullableAttribute(...)] | 0 | 0 | -| System.Threading.AsyncLocalValueChangedArgs`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.AsyncLocalValueChangedArgs`1 | [NullableContextAttribute(...)] | 0 | 2 | | System.Threading.AsyncLocal`1 | [NullableAttribute(...)] | 0 | 0 | | System.Threading.AsyncLocal`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.CancellationToken | [DebuggerDisplayAttribute(...)] | 0 | IsCancellationRequested = {IsCancellationRequested} | @@ -2373,6 +2705,8 @@ attrArgPositional | System.Threading.CompressedStack | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.EventWaitHandle | [NullableAttribute(...)] | 0 | 0 | | System.Threading.EventWaitHandle | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.ExecutionContext | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.ExecutionContext | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.ExecutionContext System.Threading.Tasks.Task.CapturedContext | [NullableAttribute(...)] | 0 | 2 | | System.Threading.ExecutionContext System.Threading.Thread.ExecutionContext | [NullableAttribute(...)] | 0 | 2 | | System.Threading.IOCompletionCallback | [CLSCompliantAttribute(...)] | 0 | False | @@ -2390,6 +2724,7 @@ attrArgPositional | System.Threading.Mutex | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.Overlapped | [NullableAttribute(...)] | 0 | 0 | | System.Threading.Overlapped | [NullableContextAttribute(...)] | 0 | 2 | +| System.Threading.RegisteredWaitHandle | [UnsupportedOSPlatformAttribute(...)] | 0 | browser | | System.Threading.Semaphore | [NullableAttribute(...)] | 0 | 0 | | System.Threading.Semaphore | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.SemaphoreFullException | [NullableAttribute(...)] | 0 | 0 | @@ -2433,6 +2768,8 @@ attrArgPositional | System.Threading.Tasks.TaskCanceledException | [NullableAttribute(...)] | 0 | 0 | | System.Threading.Tasks.TaskCanceledException | [NullableContextAttribute(...)] | 0 | 2 | | System.Threading.Tasks.TaskCanceledException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Threading.Tasks.TaskCompletionSource | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Tasks.TaskCompletionSource | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.Tasks.TaskCompletionSource`1 | [NullableAttribute(...)] | 0 | 0 | | System.Threading.Tasks.TaskCompletionSource`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.Tasks.TaskExtensions | [NullableAttribute(...)] | 0 | 0 | @@ -2458,7 +2795,7 @@ attrArgPositional | System.Threading.Tasks.Task`1 | [NullableAttribute(...)] | 0 | 0 | | System.Threading.Tasks.Task`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.Tasks.UnobservedTaskExceptionEventArgs | [NullableAttribute(...)] | 0 | 0 | -| System.Threading.Tasks.UnobservedTaskExceptionEventArgs | [NullableContextAttribute(...)] | 0 | 2 | +| System.Threading.Tasks.UnobservedTaskExceptionEventArgs | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.Tasks.ValueTask | [AsyncMethodBuilderAttribute(...)] | 0 | System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder | | System.Threading.Tasks.ValueTask | [NullableAttribute(...)] | 0 | 0 | | System.Threading.Tasks.ValueTask | [NullableContextAttribute(...)] | 0 | 1 | @@ -2471,6 +2808,8 @@ attrArgPositional | System.Threading.ThreadAbortException | [NullableAttribute(...)] | 0 | 0 | | System.Threading.ThreadAbortException | [NullableContextAttribute(...)] | 0 | 2 | | System.Threading.ThreadAbortException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Threading.ThreadExceptionEventArgs | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.ThreadExceptionEventArgs | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.ThreadInterruptedException | [NullableAttribute(...)] | 0 | 0 | | System.Threading.ThreadInterruptedException | [NullableContextAttribute(...)] | 0 | 2 | | System.Threading.ThreadInterruptedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | @@ -2561,6 +2900,8 @@ attrArgPositional | System.Type System.Reflection.MemberInfo.ReflectedType | [NullableAttribute(...)] | 0 | 2 | | System.Type System.Reflection.PropertyInfo.PropertyType | [NullableAttribute(...)] | 0 | 1 | | System.Type System.Reflection.TypeDelegator.BaseType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Resources.ResourceManager.ResourceManagerMediator.UserResourceSet | [DynamicallyAccessedMembersAttribute(...)] | 0 | 7 | +| System.Type System.Resources.ResourceManager.ResourceSetType | [DynamicallyAccessedMembersAttribute(...)] | 0 | 7 | | System.Type System.Type.BaseType | [NullableAttribute(...)] | 0 | 2 | | System.Type System.Type.DeclaringType | [NullableAttribute(...)] | 0 | 2 | | System.Type System.Type.ReflectedType | [NullableAttribute(...)] | 0 | 2 | @@ -2576,7 +2917,7 @@ attrArgPositional | System.TypeUnloadedException | [NullableAttribute(...)] | 0 | 0 | | System.TypeUnloadedException | [NullableContextAttribute(...)] | 0 | 2 | | System.TypeUnloadedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | -| System.Type[] System.Reflection.ReflectionTypeLoadException.Types | [NullableAttribute(...)] | 0 | [2,1] | +| System.Type[] System.Reflection.ReflectionTypeLoadException.Types | [NullableAttribute(...)] | 0 | [1,2] | | System.TypedReference | [CLSCompliantAttribute(...)] | 0 | False | | System.TypedReference | [NullableAttribute(...)] | 0 | 0 | | System.TypedReference | [NullableContextAttribute(...)] | 0 | 1 | @@ -2634,6 +2975,12 @@ attrArgPositional | System.__DTString | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | | System.__DTString | [ObsoleteAttribute(...)] | 1 | True | | bool | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| bool System.Console.CapsLock | [SupportedOSPlatformAttribute(...)] | 0 | windows | +| bool System.Console.NumberLock | [SupportedOSPlatformAttribute(...)] | 0 | windows | +| bool System.Console.TreatControlCAsInput | [UnsupportedOSPlatformAttribute(...)] | 0 | browser | +| bool System.Reflection.Assembly.GlobalAssemblyCache | [ObsoleteAttribute(...)] | 0 | The Global Assembly Cache is not supported. | +| bool System.Reflection.Emit.AssemblyBuilder.GlobalAssemblyCache | [ObsoleteAttribute(...)] | 0 | The Global Assembly Cache is not supported. | +| bool System.Reflection.RuntimeAssembly.GlobalAssemblyCache | [ObsoleteAttribute(...)] | 0 | The Global Assembly Cache is not supported. | | bool.FalseString | [NullableAttribute(...)] | 0 | 1 | | bool.TrueString | [NullableAttribute(...)] | 0 | 1 | | byte | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | @@ -2670,7 +3017,12 @@ attrArgPositional | double | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | float | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | int | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| int System.Console.CursorLeft | [UnsupportedOSPlatformAttribute(...)] | 0 | browser | +| int System.Console.CursorTop | [UnsupportedOSPlatformAttribute(...)] | 0 | browser | +| int System.Console.LargestWindowHeight | [UnsupportedOSPlatformAttribute(...)] | 0 | browser | +| int System.Console.LargestWindowWidth | [UnsupportedOSPlatformAttribute(...)] | 0 | browser | | int System.Threading.Overlapped.EventHandle | [ObsoleteAttribute(...)] | 0 | This property is not 64-bit compatible. Use EventHandleIntPtr instead. http://go.microsoft.com/fwlink/?linkid=14202 | +| int[] System.Globalization.HebrewCalendar.Eras | [NullableAttribute(...)] | 0 | 1 | | int[] System.Globalization.StringInfo.Indexes | [NullableAttribute(...)] | 0 | 2 | | long | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | object | [ClassInterfaceAttribute(...)] | 0 | 1 | @@ -2690,6 +3042,7 @@ attrArgPositional | object System.Collections.Generic.Dictionary`2.KeyCollection.SyncRoot | [NullableAttribute(...)] | 0 | 1 | | object System.Collections.Generic.Dictionary`2.ValueCollection.Enumerator.Current | [NullableAttribute(...)] | 0 | 2 | | object System.Collections.Generic.Dictionary`2.ValueCollection.SyncRoot | [NullableAttribute(...)] | 0 | 1 | +| object System.Collections.Generic.HashSet`1.Enumerator.Current | [NullableAttribute(...)] | 0 | 2 | | object System.Collections.Generic.List`1.Enumerator.Current | [NullableAttribute(...)] | 0 | 2 | | object System.Collections.Generic.List`1.Item | [NullableAttribute(...)] | 0 | 2 | | object System.Collections.Hashtable.Item | [NullableAttribute(...)] | 0 | 2 | @@ -2736,15 +3089,22 @@ attrArgPositional | string | [NullableContextAttribute(...)] | 0 | 1 | | string | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | string System.AppContext.BaseDirectory | [NullableAttribute(...)] | 0 | 1 | -| string System.AppDomain.FriendlyName | [NullableAttribute(...)] | 0 | 1 | +| string System.AppDomain.DynamicDirectory | [NullableAttribute(...)] | 0 | 2 | +| string System.AppDomain.RelativeSearchPath | [NullableAttribute(...)] | 0 | 2 | +| string System.ApplicationId.Culture | [NullableAttribute(...)] | 0 | 2 | +| string System.ApplicationId.ProcessorArchitecture | [NullableAttribute(...)] | 0 | 2 | | string System.ArgumentException.Message | [NullableAttribute(...)] | 0 | 1 | | string System.ArgumentOutOfRangeException.Message | [NullableAttribute(...)] | 0 | 1 | | string System.BadImageFormatException.Message | [NullableAttribute(...)] | 0 | 1 | +| string System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute.Url | [NullableAttribute(...)] | 0 | 2 | | string System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.Category | [NullableAttribute(...)] | 0 | 1 | | string System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.CheckId | [NullableAttribute(...)] | 0 | 1 | +| string System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute.Category | [NullableAttribute(...)] | 0 | 1 | +| string System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute.CheckId | [NullableAttribute(...)] | 0 | 1 | | string System.Diagnostics.Contracts.ContractException.Failure | [NullableAttribute(...)] | 0 | 1 | | string System.Diagnostics.Contracts.ContractOptionAttribute.Value | [NullableAttribute(...)] | 0 | 2 | | string System.Diagnostics.DebuggerDisplayAttribute.Value | [NullableAttribute(...)] | 0 | 1 | +| string System.Diagnostics.DebuggerTypeProxyAttribute.ProxyTypeName | [DynamicallyAccessedMembersAttribute(...)] | 0 | -1 | | string System.Diagnostics.DebuggerTypeProxyAttribute.ProxyTypeName | [NullableAttribute(...)] | 0 | 1 | | string System.Diagnostics.DebuggerVisualizerAttribute.VisualizerTypeName | [NullableAttribute(...)] | 0 | 1 | | string System.Diagnostics.Tracing.EventFieldAttribute.Name | [NullableAttribute(...)] | 0 | 2 | @@ -2775,6 +3135,7 @@ attrArgPositional | string System.Reflection.TypeDelegator.AssemblyQualifiedName | [NullableAttribute(...)] | 0 | 2 | | string System.Reflection.TypeDelegator.FullName | [NullableAttribute(...)] | 0 | 2 | | string System.Reflection.TypeDelegator.Namespace | [NullableAttribute(...)] | 0 | 2 | +| string System.Runtime.CompilerServices.SwitchExpressionException.Message | [NullableAttribute(...)] | 0 | 1 | | string System.Runtime.Intrinsics.Vector64`1.DisplayString | [NullableAttribute(...)] | 0 | 1 | | string System.Runtime.Intrinsics.Vector128`1.DisplayString | [NullableAttribute(...)] | 0 | 1 | | string System.Runtime.Intrinsics.Vector256`1.DisplayString | [NullableAttribute(...)] | 0 | 1 | diff --git a/csharp/ql/test/library-tests/cil/attributes/attribute.ql b/csharp/ql/test/library-tests/cil/attributes/attribute.ql index a0e56a607bf..ce5ed1e1daf 100644 --- a/csharp/ql/test/library-tests/cil/attributes/attribute.ql +++ b/csharp/ql/test/library-tests/cil/attributes/attribute.ql @@ -1,8 +1,11 @@ import semmle.code.cil.Attribute import semmle.code.cil.Declaration +private predicate isOsSpecific(Declaration d) { d.getQualifiedName().matches("%libobjc%") } + query predicate attrNoArg(string dec, string attr) { exists(Declaration d, Attribute a | + not isOsSpecific(d) and a.getDeclaration() = d and not exists(a.getAnArgument()) | @@ -14,6 +17,7 @@ query predicate attrNoArg(string dec, string attr) { query predicate attrArgNamed(string dec, string attr, string name, string value) { exists(Declaration d, Attribute a | a.getDeclaration() = d and + not isOsSpecific(d) and a.getNamedArgument(name) = value | dec = d.toStringWithTypes() and @@ -24,6 +28,7 @@ query predicate attrArgNamed(string dec, string attr, string name, string value) query predicate attrArgPositional(string dec, string attr, int index, string value) { exists(Declaration d, Attribute a | a.getDeclaration() = d and + not isOsSpecific(d) and a.getArgument(index) = value | dec = d.toStringWithTypes() and diff --git a/csharp/ql/test/library-tests/cil/dataflow/CallableReturns.expected b/csharp/ql/test/library-tests/cil/dataflow/CallableReturns.expected index 42ad6de6cf2..e71d177d5ef 100644 --- a/csharp/ql/test/library-tests/cil/dataflow/CallableReturns.expected +++ b/csharp/ql/test/library-tests/cil/dataflow/CallableReturns.expected @@ -24,7 +24,7 @@ alwaysNonNull | System.String System.ThrowHelper.GetArgumentName(System.ExceptionArgument) | | System.Text.Encoder System.Text.ASCIIEncoding.GetEncoder() | | System.Text.Encoder System.Text.Encoding.GetEncoder() | -| System.Text.Encoder System.Text.EncodingNLS.GetEncoder() | +| System.Text.Encoder System.Text.Latin1Encoding.GetEncoder() | | System.Text.Encoder System.Text.UTF7Encoding.GetEncoder() | | System.Text.Encoder System.Text.UTF8Encoding.GetEncoder() | | System.Text.Encoder System.Text.UTF32Encoding.GetEncoder() | @@ -38,6 +38,7 @@ alwaysThrows | System.Void System.ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException`1(!0) | System.ArgumentException | 0: ldarg.0, 1: box, 2: call System.ThrowHelper.GetAddingDuplicateWithKeyArgumentException, 3: throw | | System.Void System.ThrowHelper.ThrowAggregateException(System.Collections.Generic.List) | System.AggregateException | 0: ldarg.0, 1: newobj System.AggregateException..ctor, 2: throw | | System.Void System.ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType() | System.ArgumentException | 0: call System.SR.get_Argument_InvalidArrayType, 1: newobj System.ArgumentException..ctor, 2: throw | +| System.Void System.ThrowHelper.ThrowArgumentException_BadComparer(System.Object) | System.ArgumentException | 0: call System.SR.get_Arg_BogusIComparer, 1: ldarg.0, 2: call System.SR.Format, 3: newobj System.ArgumentException..ctor, 4: throw | | System.Void System.ThrowHelper.ThrowArgumentException_CannotExtractScalar(System.ExceptionArgument) | System.ArgumentException | 0: ldc.i4.s 31, 1: ldarg.0, 2: call System.ThrowHelper.GetArgumentException, 3: throw | | System.Void System.ThrowHelper.ThrowArgumentException_DestinationTooShort() | System.ArgumentException | 0: call System.SR.get_Argument_DestinationTooShort, 1: ldstr "destination", 2: newobj System.ArgumentException..ctor, 3: throw | | System.Void System.ThrowHelper.ThrowArgumentException_OverlapAlignmentMismatch() | System.ArgumentException | 0: call System.SR.get_Argument_OverlapAlignmentMismatch, 1: newobj System.ArgumentException..ctor, 2: throw | @@ -46,7 +47,11 @@ alwaysThrows | System.Void System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument) | System.ArgumentOutOfRangeException | 0: ldarg.0, 1: call System.ThrowHelper.GetArgumentName, 2: newobj System.ArgumentOutOfRangeException..ctor, 3: throw | | System.Void System.ThrowHelper.ThrowArgumentOutOfRangeException_PrecisionTooLarge() | System.ArgumentOutOfRangeException | 0: ldstr "precision", 1: call System.SR.get_Argument_PrecisionTooLarge, 2: ldc.i4.s 31, 3: box, 4: call System.SR.Format, 5: newobj System.ArgumentOutOfRangeException..ctor, 6: throw | | System.Void System.ThrowHelper.ThrowArgumentOutOfRangeException_SymbolDoesNotFit() | System.ArgumentOutOfRangeException | 0: ldstr "symbol", 1: call System.SR.get_Argument_BadFormatSpecifier, 2: newobj System.ArgumentOutOfRangeException..ctor, 3: throw | +| System.Void System.ThrowHelper.ThrowArgumentOutOfRange_BadHourMinuteSecond() | System.ArgumentOutOfRangeException | 0: ldnull, 1: call System.SR.get_ArgumentOutOfRange_BadHourMinuteSecond, 2: newobj System.ArgumentOutOfRangeException..ctor, 3: throw | +| System.Void System.ThrowHelper.ThrowArgumentOutOfRange_BadYearMonthDay() | System.ArgumentOutOfRangeException | 0: ldnull, 1: call System.SR.get_ArgumentOutOfRange_BadYearMonthDay, 2: newobj System.ArgumentOutOfRangeException..ctor, 3: throw | | System.Void System.ThrowHelper.ThrowArgumentOutOfRange_IndexException() | System.ArgumentOutOfRangeException | 0: ldc.i4.s 31, 1: ldc.i4.0, 2: call System.ThrowHelper.GetArgumentOutOfRangeException, 3: throw | +| System.Void System.ThrowHelper.ThrowArgumentOutOfRange_TimeSpanTooLong() | System.ArgumentOutOfRangeException | 0: ldnull, 1: call System.SR.get_Overflow_TimeSpanTooLong, 2: newobj System.ArgumentOutOfRangeException..ctor, 3: throw | +| System.Void System.ThrowHelper.ThrowArgumentOutOfRange_Year() | System.ArgumentOutOfRangeException | 0: ldc.i4.s 31, 1: ldc.i4.4, 2: call System.ThrowHelper.GetArgumentOutOfRangeException, 3: throw | | System.Void System.ThrowHelper.ThrowArraySegmentCtorValidationFailedExceptions(System.Array,System.Int32,System.Int32) | System.Exception | 0: ldarg.0, 1: ldarg.1, 2: ldarg.2, 3: call System.ThrowHelper.GetArraySegmentCtorValidationFailedException, 4: throw | | System.Void System.ThrowHelper.ThrowArrayTypeMismatchException() | System.ArrayTypeMismatchException | 0: newobj System.ArrayTypeMismatchException..ctor, 1: throw | | System.Void System.ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count() | System.ArgumentOutOfRangeException | 0: ldc.i4.s 31, 1: ldc.i4.3, 2: call System.ThrowHelper.GetArgumentOutOfRangeException, 3: throw | diff --git a/csharp/ql/test/library-tests/cil/enums/enums.expected b/csharp/ql/test/library-tests/cil/enums/enums.expected index dd2907bc5d5..6ffcb85f860 100644 --- a/csharp/ql/test/library-tests/cil/enums/enums.expected +++ b/csharp/ql/test/library-tests/cil/enums/enums.expected @@ -3,6 +3,7 @@ | Interop.Error | int | | Interop.Globalization.ResultCode | int | | Interop.Globalization.TimeZoneDisplayNameType | int | +| Interop.PollEvents | short | | Interop.Sys.AccessMode | int | | Interop.Sys.ControlCharacterNames | int | | Interop.Sys.CtrlCode | int | @@ -11,7 +12,6 @@ | Interop.Sys.LockOperations | int | | Interop.Sys.NodeType | int | | Interop.Sys.OpenFlags | int | -| Interop.Sys.PollEvents | short | | Interop.Sys.SeekWhence | int | | Interop.Sys.SysConfName | int | | Interop.Sys.SysLogPriority | int | @@ -19,7 +19,6 @@ | System.Base64FormattingOptions | int | | System.Buffers.ArrayPoolEventSource.BufferAllocatedReason | int | | System.Buffers.OperationStatus | int | -| System.Buffers.Text.FormattingHelpers.HexCasing | uint | | System.Buffers.Text.Utf8Parser.ComponentParseResult | byte | | System.Buffers.Text.Utf8Parser.ParseNumberOptions | int | | System.Buffers.TlsOverPerCoreLockedStacksArrayPool.MemoryPressure | int | @@ -39,6 +38,7 @@ | System.DayOfWeek | int | | System.DefaultBinder.Primitives | int | | System.DelegateBindingFlags | int | +| System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes | int | | System.Diagnostics.Contracts.ContractFailureKind | int | | System.Diagnostics.DebuggableAttribute.DebuggingModes | int | | System.Diagnostics.DebuggerBrowsableState | int | @@ -55,6 +55,7 @@ | System.Diagnostics.Tracing.EventLevel | int | | System.Diagnostics.Tracing.EventManifestOptions | int | | System.Diagnostics.Tracing.EventOpcode | int | +| System.Diagnostics.Tracing.EventPipeMetadataGenerator.MetadataTag | int | | System.Diagnostics.Tracing.EventPipeSerializationFormat | int | | System.Diagnostics.Tracing.EventProvider.WriteEventErrorCode | int | | System.Diagnostics.Tracing.EventProviderType | int | @@ -70,10 +71,11 @@ | System.ExceptionArgument | int | | System.ExceptionResource | int | | System.GC.EndNoGCRegionStatus | int | +| System.GC.GC_ALLOC_FLAGS | int | | System.GC.StartNoGCRegionStatus | int | | System.GCCollectionMode | int | +| System.GCKind | int | | System.GCNotificationStatus | int | -| System.Globalization.BidiCategory | int | | System.Globalization.CalendarAlgorithmType | int | | System.Globalization.CalendarDataType | int | | System.Globalization.CalendarId | ushort | @@ -93,9 +95,10 @@ | System.Globalization.HebrewNumber.HS | sbyte | | System.Globalization.HebrewNumber.HebrewToken | short | | System.Globalization.HebrewNumberParsingState | int | -| System.Globalization.LocaleDataParts | int | +| System.Globalization.IcuLocaleDataParts | int | | System.Globalization.MonthNameStyles | int | | System.Globalization.NumberStyles | int | +| System.Globalization.StrongBidiCategory | int | | System.Globalization.TextInfo.Tristate | byte | | System.Globalization.TimeSpanFormat.StandardFormat | int | | System.Globalization.TimeSpanParse.TTT | byte | @@ -103,6 +106,7 @@ | System.Globalization.TimeSpanStyles | int | | System.Globalization.UnicodeCategory | int | | System.Guid.GuidParseThrowStyle | byte | +| System.HexConverter.Casing | uint | | System.IO.FileAccess | int | | System.IO.FileAttributes | int | | System.IO.FileMode | int | @@ -111,6 +115,7 @@ | System.IO.HandleInheritability | int | | System.IO.SeekOrigin | int | | System.LazyState | int | +| System.LoaderOptimization | int | | System.MidpointRounding | int | | System.Number.NumberBufferKind | byte | | System.Number.ParsingStatus | int | @@ -158,6 +163,7 @@ | System.Reflection.TypeAttributes | int | | System.Resources.ResourceTypeCode | int | | System.Resources.UltimateResourceFallbackLocation | int | +| System.Runtime.CompilerServices.CastHelpers.CastResult | int | | System.Runtime.CompilerServices.CompilationRelaxations | int | | System.Runtime.CompilerServices.LoadHint | int | | System.Runtime.CompilerServices.MethodCodeType | int | @@ -186,6 +192,8 @@ | System.Runtime.InteropServices.ComTypes.TYPEKIND | int | | System.Runtime.InteropServices.ComTypes.VARFLAGS | short | | System.Runtime.InteropServices.ComTypes.VARKIND | int | +| System.Runtime.InteropServices.CreateComInterfaceFlags | int | +| System.Runtime.InteropServices.CreateObjectFlags | int | | System.Runtime.InteropServices.CustomQueryInterfaceMode | int | | System.Runtime.InteropServices.CustomQueryInterfaceResult | int | | System.Runtime.InteropServices.DllImportSearchPath | int | @@ -196,20 +204,27 @@ | System.Runtime.Intrinsics.X86.FloatComparisonMode | byte | | System.Runtime.Loader.AssemblyLoadContext.InternalState | int | | System.Runtime.Serialization.StreamingContextStates | int | +| System.Runtime.Versioning.ComponentGuaranteesOptions | int | +| System.Runtime.Versioning.ResourceScope | int | +| System.Runtime.Versioning.SxSRequirements | int | | System.RuntimeType.MemberListType | int | | System.RuntimeType.RuntimeTypeCache.CacheType | int | | System.Security.PartialTrustVisibilityLevel | int | | System.Security.Permissions.PermissionState | int | +| System.Security.Permissions.SecurityAction | int | +| System.Security.Permissions.SecurityPermissionFlag | int | | System.Security.Principal.PrincipalPolicy | int | +| System.Security.Principal.TokenImpersonationLevel | int | | System.Security.SecurityCriticalScope | int | | System.Security.SecurityRuleSet | byte | -| System.String.TrimType | int | | System.StringComparison | int | | System.StringSplitOptions | int | | System.StubHelpers.AsAnyMarshaler.BackPropAction | int | | System.TermInfo.WellKnownNumbers | int | | System.TermInfo.WellKnownStrings | int | | System.Text.NormalizationForm | int | +| System.Text.TrimType | int | +| System.Text.Unicode.GraphemeClusterBreakType | int | | System.Threading.ApartmentState | int | | System.Threading.EventResetMode | int | | System.Threading.LazyThreadSafetyMode | int | @@ -218,6 +233,9 @@ | System.Threading.ReaderWriterLockSlim.EnterSpinLockReason | int | | System.Threading.ReaderWriterLockSlim.WaiterStates | byte | | System.Threading.StackCrawlMark | int | +| System.Threading.Tasks.AsyncCausalityStatus | int | +| System.Threading.Tasks.CausalityRelation | int | +| System.Threading.Tasks.CausalitySynchronousWork | int | | System.Threading.Tasks.ConcurrentExclusiveSchedulerPair.ProcessingMode | byte | | System.Threading.Tasks.InternalTaskOptions | int | | System.Threading.Tasks.Sources.ValueTaskSourceOnCompletedFlags | int | diff --git a/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.expected b/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.expected index 0e26dc0592c..aa33d68fd46 100644 --- a/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.expected +++ b/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.expected @@ -6,7 +6,9 @@ fnptr | delegate* managed | 2 | Int32 | 0 | | delegate* managed | 1 | Void* | 0 | | delegate* managed | 0 | Int32 | 0 | +| delegate* managed | 3 | void | 0 | | delegate* managed | 1 | Int32* | 0 | +| delegate* unmanaged | 2 | void | 9 | | delegate* unmanaged[StdCall] | 3 | void | 2 | params | delegate* managed | 0 | Parameter 0 of delegate* managed | !0 | @@ -18,7 +20,12 @@ params | delegate* managed | 0 | Parameter 0 of delegate* managed | Int32& | | delegate* managed | 1 | Parameter 1 of delegate* managed | Object& | | delegate* managed | 0 | Parameter 0 of delegate* managed | Int32* | +| delegate* managed | 0 | Parameter 0 of delegate* managed | IntPtr | +| delegate* managed | 1 | Parameter 1 of delegate* managed | IntPtr | +| delegate* managed | 2 | Parameter 2 of delegate* managed | IntPtr* | | delegate* managed | 0 | Parameter 0 of delegate* managed | Void* | +| delegate* unmanaged | 0 | Parameter 0 of delegate* unmanaged | Char* | +| delegate* unmanaged | 1 | Parameter 1 of delegate* unmanaged | IntPtr | | delegate* unmanaged[StdCall] | 0 | Parameter 0 of delegate* unmanaged[StdCall] | Int32& | | delegate* unmanaged[StdCall] | 1 | Parameter 1 of delegate* unmanaged[StdCall] | Object& | | delegate* unmanaged[StdCall] | 2 | Parameter 2 of delegate* unmanaged[StdCall] | !0 | diff --git a/csharp/ql/test/library-tests/cil/init-only-prop/customModifiers.expected b/csharp/ql/test/library-tests/cil/init-only-prop/customModifiers.expected index 8845c0e76f4..9017f391006 100644 --- a/csharp/ql/test/library-tests/cil/init-only-prop/customModifiers.expected +++ b/csharp/ql/test/library-tests/cil/init-only-prop/customModifiers.expected @@ -1,13 +1,10 @@ | AsRef | System.Runtime.InteropServices.InAttribute | modreq | -| BeginInvoke | System.Runtime.InteropServices.InAttribute | modreq | -| EndInvoke | System.Runtime.InteropServices.InAttribute | modreq | | EventWriteTransfer | System.Runtime.InteropServices.InAttribute | modreq | | GetPinnableReference | System.Runtime.InteropServices.InAttribute | modreq | | Invoke | System.Runtime.InteropServices.InAttribute | modreq | | Max | System.Runtime.InteropServices.InAttribute | modreq | | Min | System.Runtime.InteropServices.InAttribute | modreq | | Value | System.Runtime.CompilerServices.IsVolatile | modreq | -| _bufferedValues | System.Runtime.CompilerServices.IsVolatile | modreq | | _bufferedValuesIndex | System.Runtime.CompilerServices.IsVolatile | modreq | | _callbackPartitions | System.Runtime.CompilerServices.IsVolatile | modreq | | _canceled | System.Runtime.CompilerServices.IsVolatile | modreq | @@ -23,7 +20,6 @@ | _notifyWhenNoCallbacksRunning | System.Runtime.CompilerServices.IsVolatile | modreq | | _oldKeepAlive | System.Runtime.CompilerServices.IsVolatile | modreq | | _owner | System.Runtime.CompilerServices.IsVolatile | modreq | -| _pauseTicks | System.Runtime.CompilerServices.IsVolatile | modreq | | _previous | System.Runtime.CompilerServices.IsVolatile | modreq | | _queues | System.Runtime.CompilerServices.IsVolatile | modreq | | _saDurationFormats | System.Runtime.CompilerServices.IsVolatile | modreq | @@ -80,23 +76,21 @@ | s_DefaultThreadCurrentCulture | System.Runtime.CompilerServices.IsVolatile | modreq | | s_DefaultThreadCurrentUICulture | System.Runtime.CompilerServices.IsVolatile | modreq | | s_Invariant | System.Runtime.CompilerServices.IsVolatile | modreq | -| s_LcidCachedCultures | System.Runtime.CompilerServices.IsVolatile | modreq | -| s_NameCachedCultures | System.Runtime.CompilerServices.IsVolatile | modreq | | s_anonymouslyHostedDynamicMethodsModule | System.Runtime.CompilerServices.IsVolatile | modreq | | s_cachedCultures | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_cachedCulturesByLcid | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_cachedCulturesByName | System.Runtime.CompilerServices.IsVolatile | modreq | | s_cachedRegions | System.Runtime.CompilerServices.IsVolatile | modreq | | s_currentRegionInfo | System.Runtime.CompilerServices.IsVolatile | modreq | | s_defaultBinder | System.Runtime.CompilerServices.IsVolatile | modreq | | s_defaultInstance | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_encoding | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_haveProcessId | System.Runtime.CompilerServices.IsVolatile | modreq | | s_indentSize | System.Runtime.CompilerServices.IsVolatile | modreq | | s_initialized | System.Runtime.CompilerServices.IsVolatile | modreq | -| s_invariant | System.Runtime.CompilerServices.IsVolatile | modreq | | s_invariantInfo | System.Runtime.CompilerServices.IsVolatile | modreq | | s_jajpDTFI | System.Runtime.CompilerServices.IsVolatile | modreq | | s_japaneseEraInfo | System.Runtime.CompilerServices.IsVolatile | modreq | -| s_knownWords | System.Runtime.CompilerServices.IsVolatile | modreq | -| s_lastProcessorCountRefreshTicks | System.Runtime.CompilerServices.IsVolatile | modreq | -| s_processorCount | System.Runtime.CompilerServices.IsVolatile | modreq | | s_provider | System.Runtime.CompilerServices.IsVolatile | modreq | | s_providers | System.Runtime.CompilerServices.IsVolatile | modreq | | s_regionNames | System.Runtime.CompilerServices.IsVolatile | modreq | @@ -104,4 +98,3 @@ | s_userDefaultUICulture | System.Runtime.CompilerServices.IsVolatile | modreq | | s_zhtwDTFI | System.Runtime.CompilerServices.IsVolatile | modreq | | set_Prop2 | System.Runtime.CompilerServices.IsExternalInit | modreq | -| threadPoolInitialized | System.Runtime.CompilerServices.IsVolatile | modreq | diff --git a/csharp/ql/test/library-tests/cil/typeAnnotations/typeAnnotations.expected b/csharp/ql/test/library-tests/cil/typeAnnotations/typeAnnotations.expected index c2a2d3a76fe..bc6ec867fb0 100644 --- a/csharp/ql/test/library-tests/cil/typeAnnotations/typeAnnotations.expected +++ b/csharp/ql/test/library-tests/cil/typeAnnotations/typeAnnotations.expected @@ -3,18 +3,25 @@ | As | method | 32 | | AsMutable | method | 32 | | AsRef | method | 32 | +| Element | method | 32 | +| FindValue | method | 32 | +| GetArrayDataReference | method | 32 | +| GetBucket | method | 32 | +| GetBucketRef | method | 32 | +| GetMultiDimensionalArrayBounds | method | 32 | | GetNonNullPinnableReference | method | 32 | | GetPinnableReference | method | 32 | | GetRawArrayData | method | 32 | -| GetRawArrayGeometry | method | 32 | | GetRawData | method | 32 | | GetRawStringData | method | 32 | -| GetRawSzArrayData | method | 32 | | GetReference | method | 32 | -| Local variable 0 of method g__SoftwareFallback\|66_0 | local | 32 | +| LdelemaRef | method | 32 | +| Local variable 0 of method g__SoftwareFallback\|68_0 | local | 32 | | Local variable 0 of method Add | local | 32 | | Local variable 0 of method Clear | local | 32 | -| Local variable 0 of method EnumCalendarInfoCallback | local | 32 | +| Local variable 0 of method CompareTo | local | 32 | +| Local variable 0 of method Contains | local | 32 | +| Local variable 0 of method FindValue | local | 32 | | Local variable 0 of method GetElement | local | 32 | | Local variable 0 of method GetHashCode | local | 32 | | Local variable 0 of method GetPinnableReference | local | 32 | @@ -24,18 +31,21 @@ | Local variable 0 of method Memmove | local | 32 | | Local variable 0 of method MoveNext | local | 32 | | Local variable 0 of method Multiply | local | 32 | +| Local variable 0 of method PickPivotAndPartition | local | 32 | +| Local variable 0 of method Remove | local | 32 | | Local variable 0 of method RemoveIndex | local | 32 | | Local variable 0 of method Reverse | local | 32 | | Local variable 0 of method RunOrScheduleAction | local | 32 | +| Local variable 0 of method SwapIfGreaterWithValues | local | 32 | | Local variable 0 of method ToUInt64 | local | 32 | | Local variable 0 of method TryDecodeFromUtf16 | local | 32 | +| Local variable 0 of method TryGetValue | local | 32 | | Local variable 0 of method TryParseExactD | local | 32 | | Local variable 0 of method TryParseExactN | local | 32 | | Local variable 0 of method ValueToHexString | local | 32 | | Local variable 0 of method ValueToString | local | 32 | +| Local variable 0 of method get_Item | local | 32 | | Local variable 1 of method .ctor | local | 32 | -| Local variable 1 of method g__SoftwareFallback\|32_0 | local | 32 | -| Local variable 1 of method g__SoftwareFallback\|33_0 | local | 32 | | Local variable 1 of method g__SoftwareFallback\|34_0 | local | 32 | | Local variable 1 of method g__SoftwareFallback\|35_0 | local | 32 | | Local variable 1 of method g__SoftwareFallback\|36_0 | local | 32 | @@ -44,20 +54,30 @@ | Local variable 1 of method g__SoftwareFallback\|39_0 | local | 32 | | Local variable 1 of method g__SoftwareFallback\|40_0 | local | 32 | | Local variable 1 of method g__SoftwareFallback\|41_0 | local | 32 | -| Local variable 1 of method b__32_0 | local | 32 | -| Local variable 1 of method b__113_0 | local | 32 | -| Local variable 1 of method g__SoftwareFallback\|67_0 | local | 32 | +| Local variable 1 of method g__SoftwareFallback\|42_0 | local | 32 | +| Local variable 1 of method g__SoftwareFallback\|43_0 | local | 32 | +| Local variable 1 of method g__SoftwareFallback\|44_0 | local | 32 | +| Local variable 1 of method g__SoftwareFallback\|45_0 | local | 32 | +| Local variable 1 of method g__SoftwareFallback\|46_0 | local | 32 | +| Local variable 1 of method g__SoftwareFallback\|47_0 | local | 32 | +| Local variable 1 of method g__SoftwareFallback\|48_0 | local | 32 | +| Local variable 1 of method g__SoftwareFallback\|49_0 | local | 32 | +| Local variable 1 of method b__33_0 | local | 32 | +| Local variable 1 of method b__158_0 | local | 32 | +| Local variable 1 of method b__158_1 | local | 32 | +| Local variable 1 of method g__SoftwareFallback\|69_0 | local | 32 | +| Local variable 1 of method g__SoftwareFallback\|75_0 | local | 32 | | Local variable 1 of method Add | local | 32 | | Local variable 1 of method Append | local | 32 | | Local variable 1 of method AppendHelper | local | 32 | | Local variable 1 of method AppendJoin | local | 32 | -| Local variable 1 of method CompareString | local | 32 | -| Local variable 1 of method CompareStringOrdinalIgnoreCase | local | 32 | +| Local variable 1 of method CompareIgnoreCaseInvariantMode | local | 32 | +| Local variable 1 of method CompareStringIgnoreCase | local | 32 | +| Local variable 1 of method CompareTo | local | 32 | | Local variable 1 of method Convert | local | 32 | -| Local variable 1 of method Create | local | 32 | | Local variable 1 of method CreateActivityPathGuid | local | 32 | -| Local variable 1 of method EndsWith | local | 32 | -| Local variable 1 of method FillStringChecked | local | 32 | +| Local variable 1 of method EnumCalendarInfoCallback | local | 32 | +| Local variable 1 of method FindValue | local | 32 | | Local variable 1 of method FromBase64CharArray | local | 32 | | Local variable 1 of method FromBase64String | local | 32 | | Local variable 1 of method FromUtf16 | local | 32 | @@ -67,6 +87,7 @@ | Local variable 1 of method GetBytes | local | 32 | | Local variable 1 of method GetBytesFromEncoding | local | 32 | | Local variable 1 of method GetBytesWithFallback | local | 32 | +| Local variable 1 of method GetCategoryCasingTableOffsetNoBoundsChecks | local | 32 | | Local variable 1 of method GetCharCount | local | 32 | | Local variable 1 of method GetCharCountWithFallback | local | 32 | | Local variable 1 of method GetChars | local | 32 | @@ -74,32 +95,39 @@ | Local variable 1 of method GetEnvironmentVariable | local | 32 | | Local variable 1 of method GetHashCode | local | 32 | | Local variable 1 of method GetNonRandomizedHashCode | local | 32 | +| Local variable 1 of method GetNumericGraphemeTableOffsetNoBoundsChecks | local | 32 | +| Local variable 1 of method GetNumericValueNoBoundsCheck | local | 32 | | Local variable 1 of method GetString | local | 32 | | Local variable 1 of method GetUnicode | local | 32 | +| Local variable 1 of method GetUpperBound | local | 32 | +| Local variable 1 of method IcuCompareString | local | 32 | +| Local variable 1 of method IcuEndsWith | local | 32 | +| Local variable 1 of method IcuGetSortKeyLength | local | 32 | +| Local variable 1 of method IcuIndexOfCore | local | 32 | +| Local variable 1 of method IcuStartsWith | local | 32 | | Local variable 1 of method IndexOf | local | 32 | -| Local variable 1 of method IndexOfCore | local | 32 | | Local variable 1 of method IndexOfOrdinalHelper | local | 32 | | Local variable 1 of method IndexOfOrdinalIgnoreCaseHelper | local | 32 | | Local variable 1 of method Insert | local | 32 | | Local variable 1 of method InternalCopy | local | 32 | | Local variable 1 of method InvariantIndexOf | local | 32 | -| Local variable 1 of method InvariantLastIndexOf | local | 32 | | Local variable 1 of method IsAscii | local | 32 | -| Local variable 1 of method IsSortable | local | 32 | | Local variable 1 of method Join | local | 32 | | Local variable 1 of method LastIndexOf | local | 32 | | Local variable 1 of method MatchChars | local | 32 | | Local variable 1 of method Memmove | local | 32 | +| Local variable 1 of method PickPivotAndPartition | local | 32 | | Local variable 1 of method Pow10 | local | 32 | | Local variable 1 of method ReplaceAllInChunk | local | 32 | | Local variable 1 of method Reverse | local | 32 | -| Local variable 1 of method StartsWith | local | 32 | | Local variable 1 of method TZif_ToInt32 | local | 32 | | Local variable 1 of method TZif_ToInt64 | local | 32 | | Local variable 1 of method ThreadSafeCopy | local | 32 | | Local variable 1 of method ToLowerAsciiInvariant | local | 32 | +| Local variable 1 of method ToString | local | 32 | | Local variable 1 of method ToUpperAsciiInvariant | local | 32 | | Local variable 1 of method ToUtf16 | local | 32 | +| Local variable 1 of method TraceOperationBegin | local | 32 | | Local variable 1 of method Trim | local | 32 | | Local variable 1 of method TrimEnd | local | 32 | | Local variable 1 of method TrimStart | local | 32 | @@ -107,7 +135,6 @@ | Local variable 1 of method TryStringToNumber | local | 32 | | Local variable 1 of method WaitMultipleIgnoringSyncContext | local | 32 | | Local variable 1 of method WithElement | local | 32 | -| Local variable 1 of method WithUpper | local | 32 | | Local variable 1 of method WriteEvent | local | 32 | | Local variable 1 of method WriteImpl | local | 32 | | Local variable 1 of method WriteMultiMerge | local | 32 | @@ -115,29 +142,33 @@ | Local variable 1 of method get_Item | local | 32 | | Local variable 2 of method .ctor | local | 32 | | Local variable 2 of method ChangeCaseCommon | local | 32 | +| Local variable 2 of method CompareIgnoreCaseInvariantMode | local | 32 | | Local variable 2 of method CompareOrdinalHelper | local | 32 | -| Local variable 2 of method CompareOrdinalIgnoreCase | local | 32 | +| Local variable 2 of method CompareStringIgnoreCase | local | 32 | +| Local variable 2 of method Copy | local | 32 | | Local variable 2 of method CopyTo | local | 32 | -| Local variable 2 of method CreateSortKey | local | 32 | | Local variable 2 of method Ctor | local | 32 | +| Local variable 2 of method Decompose | local | 32 | | Local variable 2 of method DoAnsiConversion | local | 32 | | Local variable 2 of method EndsWithOrdinalHelper | local | 32 | | Local variable 2 of method EndsWithOrdinalIgnoreCaseHelper | local | 32 | | Local variable 2 of method EqualStartingCharacterCount | local | 32 | +| Local variable 2 of method GenerateMetadataForNamedTypeV2 | local | 32 | | Local variable 2 of method GetByteCount | local | 32 | | Local variable 2 of method GetBytes | local | 32 | | Local variable 2 of method GetChars | local | 32 | | Local variable 2 of method GetValue | local | 32 | -| Local variable 2 of method IndexOfCore | local | 32 | -| Local variable 2 of method IndexOfOrdinalCore | local | 32 | +| Local variable 2 of method IcuCreateSortKey | local | 32 | +| Local variable 2 of method IcuGetSortKey | local | 32 | +| Local variable 2 of method IcuIsNormalized | local | 32 | | Local variable 2 of method Insert | local | 32 | -| Local variable 2 of method InternalGetNumericValue | local | 32 | -| Local variable 2 of method InternalSubString | local | 32 | -| Local variable 2 of method InvariantCreateSortKey | local | 32 | -| Local variable 2 of method LastIndexOfCore | local | 32 | -| Local variable 2 of method LastIndexOfOrdinalCore | local | 32 | +| Local variable 2 of method IntersectWithHashSetWithSameComparer | local | 32 | +| Local variable 2 of method IntroSort | local | 32 | +| Local variable 2 of method MemberwiseClone | local | 32 | | Local variable 2 of method Multiply | local | 32 | +| Local variable 2 of method PickPivotAndPartition | local | 32 | | Local variable 2 of method ReadNative | local | 32 | +| Local variable 2 of method Remove | local | 32 | | Local variable 2 of method SetValue | local | 32 | | Local variable 2 of method StartsWithOrdinalHelper | local | 32 | | Local variable 2 of method StartsWithOrdinalIgnoreCaseHelper | local | 32 | @@ -149,47 +180,51 @@ | Local variable 2 of method TryUInt32ToDecStr | local | 32 | | Local variable 2 of method TryUInt64ToDecStr | local | 32 | | Local variable 2 of method Write | local | 32 | +| Local variable 3 of method b__29_0 | local | 32 | +| Local variable 3 of method b__30_0 | local | 32 | | Local variable 3 of method AddCustomAttributes | local | 32 | -| Local variable 3 of method CompareOrdinalIgnoreCase | local | 32 | -| Local variable 3 of method CompareString | local | 32 | -| Local variable 3 of method CompareStringOrdinalIgnoreCase | local | 32 | +| Local variable 3 of method CompareStringIgnoreCase | local | 32 | | Local variable 3 of method Convert | local | 32 | | Local variable 3 of method Copy | local | 32 | | Local variable 3 of method CreateInstance | local | 32 | | Local variable 3 of method CreateStringFromEncoding | local | 32 | -| Local variable 3 of method Ctor | local | 32 | -| Local variable 3 of method EndsWith | local | 32 | +| Local variable 3 of method Enable | local | 32 | | Local variable 3 of method Fill | local | 32 | -| Local variable 3 of method FillStringChecked | local | 32 | | Local variable 3 of method FindSection | local | 32 | | Local variable 3 of method FromUtf16 | local | 32 | | Local variable 3 of method GetBytes | local | 32 | | Local variable 3 of method GetBytesWithFallback | local | 32 | | Local variable 3 of method GetChars | local | 32 | | Local variable 3 of method GetCharsWithFallback | local | 32 | +| Local variable 3 of method GetNonRandomizedHashCodeOrdinalIgnoreCase | local | 32 | +| Local variable 3 of method IcuCompareString | local | 32 | +| Local variable 3 of method IcuEndsWith | local | 32 | +| Local variable 3 of method IcuIndexOfCore | local | 32 | +| Local variable 3 of method IcuStartsWith | local | 32 | +| Local variable 3 of method IndexOf | local | 32 | | Local variable 3 of method IndexOfCharArray | local | 32 | -| Local variable 3 of method IndexOfCore | local | 32 | | Local variable 3 of method IndexOfOrdinalHelper | local | 32 | | Local variable 3 of method IndexOfOrdinalIgnoreCaseHelper | local | 32 | | Local variable 3 of method Int32ToHexStr | local | 32 | | Local variable 3 of method Int64ToHexStr | local | 32 | | Local variable 3 of method InternalLoad | local | 32 | +| Local variable 3 of method IntroSort | local | 32 | | Local variable 3 of method InvariantIndexOf | local | 32 | -| Local variable 3 of method InvariantLastIndexOf | local | 32 | | Local variable 3 of method JoinInternal | local | 32 | +| Local variable 3 of method LastIndexOf | local | 32 | | Local variable 3 of method LastIndexOfCharArray | local | 32 | +| Local variable 3 of method MemberwiseClone | local | 32 | | Local variable 3 of method NegativeInt32ToDecStr | local | 32 | +| Local variable 3 of method PickPivotAndPartition | local | 32 | | Local variable 3 of method Pin | local | 32 | | Local variable 3 of method Populate | local | 32 | | Local variable 3 of method Pow10 | local | 32 | -| Local variable 3 of method Replace | local | 32 | +| Local variable 3 of method RemoveWhere | local | 32 | | Local variable 3 of method Resize | local | 32 | -| Local variable 3 of method StartsWith | local | 32 | | Local variable 3 of method StringToCoTaskMemUni | local | 32 | | Local variable 3 of method StringToHGlobalUni | local | 32 | | Local variable 3 of method ThreadSafeCopy | local | 32 | | Local variable 3 of method ToBase64String | local | 32 | -| Local variable 3 of method ToCharArray | local | 32 | | Local variable 3 of method ToString | local | 32 | | Local variable 3 of method ToUtf16 | local | 32 | | Local variable 3 of method TryNegativeInt64ToDecStr | local | 32 | @@ -199,12 +234,14 @@ | Local variable 3 of method Write | local | 32 | | Local variable 3 of method WriteEvent | local | 32 | | Local variable 3 of method WriteStdoutAnsiString | local | 32 | -| Local variable 3 of method get_Item | local | 32 | | Local variable 4 of method .ctor | local | 32 | | Local variable 4 of method AddDivisor | local | 32 | +| Local variable 4 of method AddIfNotPresent | local | 32 | | Local variable 4 of method AddNullTerminatedString | local | 32 | +| Local variable 4 of method Append | local | 32 | | Local variable 4 of method ChangeCaseCommon | local | 32 | | Local variable 4 of method CompareOrdinalHelper | local | 32 | +| Local variable 4 of method ConstructFrom | local | 32 | | Local variable 4 of method Copy | local | 32 | | Local variable 4 of method EndsWithOrdinalHelper | local | 32 | | Local variable 4 of method EndsWithOrdinalIgnoreCaseHelper | local | 32 | @@ -212,30 +249,32 @@ | Local variable 4 of method EscapeString | local | 32 | | Local variable 4 of method FormatPrintF | local | 32 | | Local variable 4 of method GetBytes | local | 32 | +| Local variable 4 of method GetBytesForSmallInput | local | 32 | | Local variable 4 of method GetChars | local | 32 | | Local variable 4 of method GetMessage | local | 32 | -| Local variable 4 of method GetUnicodeCore | local | 32 | -| Local variable 4 of method IndexOfCore | local | 32 | -| Local variable 4 of method IndexOfOrdinalCore | local | 32 | +| Local variable 4 of method IcuGetSortKey | local | 32 | +| Local variable 4 of method IcuGetUnicodeCore | local | 32 | | Local variable 4 of method InternalLoad | local | 32 | -| Local variable 4 of method InternalSubString | local | 32 | +| Local variable 4 of method IntroSort | local | 32 | | Local variable 4 of method JoinInternal | local | 32 | -| Local variable 4 of method LastIndexOfCore | local | 32 | | Local variable 4 of method MakeRoom | local | 32 | | Local variable 4 of method NegativeInt64ToDecStr | local | 32 | | Local variable 4 of method PadLeft | local | 32 | | Local variable 4 of method PadRight | local | 32 | | Local variable 4 of method Remove | local | 32 | +| Local variable 4 of method Replace | local | 32 | +| Local variable 4 of method Resize | local | 32 | | Local variable 4 of method StartsWithOrdinalHelper | local | 32 | | Local variable 4 of method StartsWithOrdinalIgnoreCaseHelper | local | 32 | -| Local variable 4 of method ToCharArray | local | 32 | | Local variable 4 of method TryInsert | local | 32 | | Local variable 4 of method Write | local | 32 | | Local variable 4 of method WriteCore | local | 32 | | Local variable 4 of method WriteEvent | local | 32 | -| Local variable 5 of method Append | local | 32 | +| Local variable 5 of method Clear | local | 32 | | Local variable 5 of method ConvertToNative | local | 32 | +| Local variable 5 of method Copy | local | 32 | | Local variable 5 of method CreateInstance | local | 32 | +| Local variable 5 of method Enable | local | 32 | | Local variable 5 of method GetAttributeUsage | local | 32 | | Local variable 5 of method GetBytes | local | 32 | | Local variable 5 of method GetBytesWithFallback | local | 32 | @@ -244,11 +283,13 @@ | Local variable 5 of method GetHomeDirectory | local | 32 | | Local variable 5 of method Insert | local | 32 | | Local variable 5 of method JoinInternal | local | 32 | +| Local variable 5 of method PickPivotAndPartition | local | 32 | | Local variable 5 of method Pow10 | local | 32 | | Local variable 5 of method Read | local | 32 | | Local variable 5 of method ReadArray | local | 32 | | Local variable 5 of method ReadCore | local | 32 | | Local variable 5 of method Replace | local | 32 | +| Local variable 5 of method Resize | local | 32 | | Local variable 5 of method StringToCoTaskMemUTF8 | local | 32 | | Local variable 5 of method StringToHGlobalUTF8 | local | 32 | | Local variable 5 of method SubtractDivisor | local | 32 | @@ -258,111 +299,101 @@ | Local variable 5 of method TryToBase64Chars | local | 32 | | Local variable 5 of method WriteArray | local | 32 | | Local variable 5 of method WriteEvent | local | 32 | -| Local variable 5 of method get_Item | local | 32 | +| Local variable 5 of method WriteWhenEncodingIsNotUtf8 | local | 32 | | Local variable 5 of method get_UserName | local | 32 | -| Local variable 6 of method .ctor | local | 32 | -| Local variable 6 of method Clear | local | 32 | +| Local variable 6 of method Append | local | 32 | +| Local variable 6 of method ConvertFixedToManaged | local | 32 | | Local variable 6 of method ConvertToBase64Array | local | 32 | +| Local variable 6 of method ConvertToNative | local | 32 | +| Local variable 6 of method Copy | local | 32 | +| Local variable 6 of method FindItemIndex | local | 32 | | Local variable 6 of method GenerateMetadataForProperty | local | 32 | -| Local variable 6 of method GetAsciiCore | local | 32 | -| Local variable 6 of method IndexOfOrdinalCore | local | 32 | +| Local variable 6 of method IcuGetAsciiCore | local | 32 | | Local variable 6 of method InternalCopy | local | 32 | | Local variable 6 of method JoinInternal | local | 32 | | Local variable 6 of method PadRight | local | 32 | +| Local variable 6 of method PickPivotAndPartition | local | 32 | | Local variable 6 of method Remove | local | 32 | -| Local variable 6 of method Replace | local | 32 | | Local variable 6 of method Resize | local | 32 | | Local variable 6 of method SetConstantValue | local | 32 | | Local variable 6 of method ToBase64CharArray | local | 32 | | Local variable 6 of method TryDecodeFromUtf16 | local | 32 | | Local variable 6 of method TryFormat | local | 32 | -| Local variable 6 of method Write | local | 32 | | Local variable 7 of method .ctor | local | 32 | -| Local variable 7 of method Append | local | 32 | +| Local variable 7 of method AddIfNotPresent | local | 32 | +| Local variable 7 of method ConvertFixedToNative | local | 32 | | Local variable 7 of method GenerateMetadata | local | 32 | | Local variable 7 of method GetBytesWithFallback | local | 32 | | Local variable 7 of method GetCharsWithFallback | local | 32 | -| Local variable 7 of method GetHashCodeOfStringCore | local | 32 | +| Local variable 7 of method IcuGetHashCodeOfString | local | 32 | +| Local variable 7 of method IcuNormalize | local | 32 | | Local variable 7 of method Insert | local | 32 | | Local variable 7 of method JoinInternal | local | 32 | | Local variable 7 of method PadLeft | local | 32 | | Local variable 7 of method Populate | local | 32 | | Local variable 7 of method Pow10 | local | 32 | -| Local variable 7 of method Remove | local | 32 | | Local variable 7 of method Resize | local | 32 | -| Local variable 7 of method WriteEventString | local | 32 | -| Local variable 7 of method get_Item | local | 32 | +| Local variable 7 of method TryInsert | local | 32 | +| Local variable 7 of method WriteWhenEncodingIsNotUtf8 | local | 32 | | Local variable 8 of method JoinInternal | local | 32 | | Local variable 8 of method Pow10 | local | 32 | -| Local variable 8 of method Replace | local | 32 | | Local variable 8 of method SetConstantValue | local | 32 | | Local variable 8 of method ToBase64CharArray | local | 32 | | Local variable 8 of method ToString | local | 32 | -| Local variable 8 of method TryInsert | local | 32 | -| Local variable 8 of method Write | local | 32 | +| Local variable 8 of method TrimExcess | local | 32 | +| Local variable 8 of method WriteEventString | local | 32 | +| Local variable 9 of method g__GetNonRandomizedHashCodeOrdinalIgnoreCaseSlow\|52_0 | local | 32 | +| Local variable 9 of method AddIfNotPresent | local | 32 | +| Local variable 9 of method Enable | local | 32 | +| Local variable 9 of method FindItemIndex | local | 32 | | Local variable 9 of method GenerateMetadataForProperty | local | 32 | -| Local variable 9 of method GetHashCodeOfStringCore | local | 32 | +| Local variable 9 of method IcuGetHashCodeOfString | local | 32 | +| Local variable 9 of method IcuNormalize | local | 32 | | Local variable 9 of method Insert | local | 32 | +| Local variable 9 of method IntersectWithEnumerable | local | 32 | | Local variable 9 of method JoinInternal | local | 32 | | Local variable 9 of method TrimExcess | local | 32 | -| Local variable 9 of method get_Item | local | 32 | | Local variable 10 of method .ctor | local | 32 | | Local variable 10 of method FormatFixed | local | 32 | | Local variable 10 of method IntToString | local | 32 | | Local variable 10 of method JoinInternal | local | 32 | | Local variable 10 of method LongToString | local | 32 | | Local variable 10 of method ReplaceAllInChunk | local | 32 | -| Local variable 11 of method GenerateMetadata | local | 32 | -| Local variable 11 of method GetHashCodeOfStringCore | local | 32 | -| Local variable 11 of method InternalReadChars | local | 32 | +| Local variable 10 of method TrimExcess | local | 32 | +| Local variable 11 of method AddIfNotPresent | local | 32 | +| Local variable 11 of method IcuGetHashCodeOfString | local | 32 | | Local variable 11 of method Resize | local | 32 | -| Local variable 11 of method get_Item | local | 32 | +| Local variable 12 of method FindItemIndex | local | 32 | | Local variable 12 of method JoinCore | local | 32 | | Local variable 13 of method .ctor | local | 32 | +| Local variable 13 of method AddIfNotPresent | local | 32 | | Local variable 13 of method ChangeCaseCommon | local | 32 | -| Local variable 13 of method get_Item | local | 32 | -| Local variable 14 of method .ctor | local | 32 | | Local variable 14 of method Resize | local | 32 | -| Local variable 15 of method get_Item | local | 32 | | Local variable 16 of method .ctor | local | 32 | -| Local variable 17 of method get_Item | local | 32 | -| Local variable 18 of method .ctor | local | 32 | | Local variable 19 of method .ctor | local | 32 | | Local variable 19 of method NumberToStringFormat | local | 32 | -| Local variable 19 of method get_Item | local | 32 | +| Local variable 21 of method GenerateMetadata | local | 32 | | Local variable 22 of method .ctor | local | 32 | | Local variable 23 of method WriteEvent | local | 32 | | Local variable 24 of method WriteEvent | local | 32 | | Local variable 25 of method .ctor | local | 32 | | Local variable 25 of method WriteEvent | local | 32 | -| Local variable 26 of method .ctor | local | 32 | | Local variable 26 of method WriteEvent | local | 32 | | Local variable 27 of method WriteEvent | local | 32 | | Local variable 28 of method .ctor | local | 32 | | Local variable 28 of method WriteEvent | local | 32 | | Local variable 29 of method WriteEvent | local | 32 | -| Local variable 30 of method .ctor | local | 32 | +| Local variable 30 of method g__SseImpl\|59_0 | local | 32 | | Local variable 30 of method WriteEvent | local | 32 | -| Local variable 31 of method .ctor | local | 32 | | Local variable 31 of method NumberToStringFormat | local | 32 | -| Local variable 33 of method .ctor | local | 32 | -| Local variable 34 of method .ctor | local | 32 | | Local variable 34 of method WriteEvent | local | 32 | -| Local variable 35 of method .ctor | local | 32 | -| Local variable 37 of method .ctor | local | 32 | -| Local variable 38 of method .ctor | local | 32 | -| Local variable 39 of method .ctor | local | 32 | -| Local variable 41 of method .ctor | local | 32 | -| Local variable 43 of method .ctor | local | 32 | -| Local variable 45 of method .ctor | local | 32 | -| Local variable 47 of method .ctor | local | 32 | -| Local variable 49 of method .ctor | local | 32 | | Max | method | 32 | | Min | method | 32 | -| Parameter 0 of g__SoftwareFallback\|10_0 | parameter | 32 | +| NullRef | method | 32 | | Parameter 0 of g__SoftwareFallback\|12_0 | parameter | 32 | -| Parameter 0 of g__IncrementX\|115_1 | parameter | 32 | -| Parameter 0 of g__IncrementY\|115_0 | parameter | 32 | +| Parameter 0 of g__SoftwareFallback\|14_0 | parameter | 32 | +| Parameter 0 of g__IncrementX\|112_1 | parameter | 32 | +| Parameter 0 of g__IncrementY\|112_0 | parameter | 32 | | Parameter 0 of Abs | parameter | 32 | | Parameter 0 of AccumulateDecimalDigitsIntoBigInteger | parameter | 32 | | Parameter 0 of Add | parameter | 32 | @@ -378,6 +409,7 @@ | Parameter 0 of AdjustHour | parameter | 32 | | Parameter 0 of AdjustTimeZoneToLocal | parameter | 32 | | Parameter 0 of AdjustTimeZoneToUniversal | parameter | 32 | +| Parameter 0 of And | parameter | 32 | | Parameter 0 of AppendParameters | parameter | 32 | | Parameter 0 of AreSame | parameter | 32 | | Parameter 0 of As | parameter | 32 | @@ -385,8 +417,11 @@ | Parameter 0 of AsPointer | parameter | 32 | | Parameter 0 of AsRef | parameter | 32 | | Parameter 0 of AssembleFloatingPointBits | parameter | 32 | +| Parameter 0 of AwaitOnCompleted | parameter | 32 | +| Parameter 0 of AwaitUnsafeOnCompleted | parameter | 32 | | Parameter 0 of BinarySearch | parameter | 32 | | Parameter 0 of Block | parameter | 32 | +| Parameter 0 of BulkMoveWithWriteBarrier | parameter | 32 | | Parameter 0 of ByteOffset | parameter | 32 | | Parameter 0 of CheckDefaultDateTime | parameter | 32 | | Parameter 0 of CheckForAvailableMemory | parameter | 32 | @@ -396,8 +431,9 @@ | Parameter 0 of ClearWithoutReferences | parameter | 32 | | Parameter 0 of Compare | parameter | 32 | | Parameter 0 of CompareExchange | parameter | 32 | -| Parameter 0 of CompareOrdinalIgnoreCase | parameter | 32 | -| Parameter 0 of CompareStringOrdinalIgnoreCase | parameter | 32 | +| Parameter 0 of CompareIgnoreCaseInvariantMode | parameter | 32 | +| Parameter 0 of CompareStringIgnoreCase | parameter | 32 | +| Parameter 0 of CompareStringIgnoreCaseNonAscii | parameter | 32 | | Parameter 0 of ComputeHash32 | parameter | 32 | | Parameter 0 of ComputeHash32OrdinalIgnoreCase | parameter | 32 | | Parameter 0 of ComputeHash32OrdinalIgnoreCaseSlow | parameter | 32 | @@ -406,6 +442,7 @@ | Parameter 0 of Contains | parameter | 32 | | Parameter 0 of ConvertBigIntegerToFloatingPointBits | parameter | 32 | | Parameter 0 of CountSignificantBits | parameter | 32 | +| Parameter 0 of Create | parameter | 32 | | Parameter 0 of CreateReadOnlySpan | parameter | 32 | | Parameter 0 of CreateSpan | parameter | 32 | | Parameter 0 of DateTimeOffsetTimeZonePostProcessing | parameter | 32 | @@ -423,12 +460,12 @@ | Parameter 0 of Div96ByConst | parameter | 32 | | Parameter 0 of Div128By96 | parameter | 32 | | Parameter 0 of DivRem | parameter | 32 | +| Parameter 0 of Element | parameter | 32 | | Parameter 0 of EncodeObject | parameter | 32 | | Parameter 0 of EnsureInitialized | parameter | 32 | | Parameter 0 of EnsureInitializedCore | parameter | 32 | | Parameter 0 of EnsureLockInitialized | parameter | 32 | -| Parameter 0 of EqualsOrdinalIgnoreCase | parameter | 32 | -| Parameter 0 of EqualsOrdinalIgnoreCaseNonAscii | parameter | 32 | +| Parameter 0 of EqualsIgnoreCase | parameter | 32 | | Parameter 0 of Exchange | parameter | 32 | | Parameter 0 of ExchangeAdd | parameter | 32 | | Parameter 0 of FormatCurrency | parameter | 32 | @@ -436,6 +473,7 @@ | Parameter 0 of FormatExponent | parameter | 32 | | Parameter 0 of FormatFixed | parameter | 32 | | Parameter 0 of FormatGeneral | parameter | 32 | +| Parameter 0 of FormatHalf | parameter | 32 | | Parameter 0 of FormatNumber | parameter | 32 | | Parameter 0 of FormatPercent | parameter | 32 | | Parameter 0 of FormatScientific | parameter | 32 | @@ -466,18 +504,13 @@ | Parameter 0 of GetExecutingAssembly | parameter | 32 | | Parameter 0 of GetHashCode | parameter | 32 | | Parameter 0 of GetHebrewDayOfNM | parameter | 32 | +| Parameter 0 of GetIUnknownImpl | parameter | 32 | | Parameter 0 of GetMaxThreads | parameter | 32 | | Parameter 0 of GetMaxThreadsNative | parameter | 32 | -| Parameter 0 of GetMemoryInfo | parameter | 32 | | Parameter 0 of GetMinThreads | parameter | 32 | | Parameter 0 of GetMinThreadsNative | parameter | 32 | | Parameter 0 of GetNextIntroducedMethod | parameter | 32 | -| Parameter 0 of GetObjectHandleOnStack | parameter | 32 | -| Parameter 0 of GetQCallAssemblyOnStack | parameter | 32 | -| Parameter 0 of GetQCallModuleOnStack | parameter | 32 | -| Parameter 0 of GetQCallTypeHandleOnStack | parameter | 32 | -| Parameter 0 of GetStackCrawlMarkHandle | parameter | 32 | -| Parameter 0 of GetStringHandleOnStack | parameter | 32 | +| Parameter 0 of GetStateMachineBox | parameter | 32 | | Parameter 0 of GetSymbolOrDefault | parameter | 32 | | Parameter 0 of GetThreadDeserializationTracker | parameter | 32 | | Parameter 0 of GetTimeOfN | parameter | 32 | @@ -485,7 +518,10 @@ | Parameter 0 of GetTimeOfNNN | parameter | 32 | | Parameter 0 of GetTimeZoneName | parameter | 32 | | Parameter 0 of GetWindowSize | parameter | 32 | +| Parameter 0 of GreaterThan | parameter | 32 | +| Parameter 0 of GrowTable | parameter | 32 | | Parameter 0 of HandleTimeZone | parameter | 32 | +| Parameter 0 of HashShift | parameter | 32 | | Parameter 0 of HeuristicDivide | parameter | 32 | | Parameter 0 of IncreaseScale | parameter | 32 | | Parameter 0 of IncreaseScale64 | parameter | 32 | @@ -494,16 +530,21 @@ | Parameter 0 of IndexOfAny | parameter | 32 | | Parameter 0 of InitBlockUnaligned | parameter | 32 | | Parameter 0 of Initialize | parameter | 32 | -| Parameter 0 of InitializeVMTp | parameter | 32 | | Parameter 0 of Int64DivMod1E9 | parameter | 32 | | Parameter 0 of InternalGetCurrentMethod | parameter | 32 | | Parameter 0 of InternalRound | parameter | 32 | | Parameter 0 of IsAddressGreaterThan | parameter | 32 | | Parameter 0 of IsAddressLessThan | parameter | 32 | +| Parameter 0 of IsNullRef | parameter | 32 | | Parameter 0 of IsUtf8ContinuationByte | parameter | 32 | +| Parameter 0 of KeepAliveViaCleanupList | parameter | 32 | +| Parameter 0 of KeyToBucket | parameter | 32 | | Parameter 0 of LastIndexOf | parameter | 32 | | Parameter 0 of LastIndexOfAny | parameter | 32 | -| Parameter 0 of LoadUIntPtr | parameter | 32 | +| Parameter 0 of LessThan | parameter | 32 | +| Parameter 0 of LoadNUInt | parameter | 32 | +| Parameter 0 of LoadUInt | parameter | 32 | +| Parameter 0 of LoadUShort | parameter | 32 | | Parameter 0 of LoadVector | parameter | 32 | | Parameter 0 of LoadVector128 | parameter | 32 | | Parameter 0 of LoadVector256 | parameter | 32 | @@ -521,13 +562,17 @@ | Parameter 0 of Min | parameter | 32 | | Parameter 0 of Multiply | parameter | 32 | | Parameter 0 of NarrowFourUtf16CharsToAsciiAndWriteToBuffer | parameter | 32 | +| Parameter 0 of NarrowFourUtf16CharsToLatin1AndWriteToBuffer | parameter | 32 | | Parameter 0 of NarrowTwoUtf16CharsToAsciiAndWriteToBuffer | parameter | 32 | +| Parameter 0 of NarrowTwoUtf16CharsToLatin1AndWriteToBuffer | parameter | 32 | | Parameter 0 of NumberToDouble | parameter | 32 | | Parameter 0 of NumberToFloatingPointBits | parameter | 32 | | Parameter 0 of NumberToFloatingPointBitsSlow | parameter | 32 | +| Parameter 0 of NumberToHalf | parameter | 32 | | Parameter 0 of NumberToSingle | parameter | 32 | | Parameter 0 of NumberToString | parameter | 32 | | Parameter 0 of NumberToStringFormat | parameter | 32 | +| Parameter 0 of Or | parameter | 32 | | Parameter 0 of OverflowUnscale | parameter | 32 | | Parameter 0 of ParseByFormat | parameter | 32 | | Parameter 0 of ParseDigits | parameter | 32 | @@ -552,8 +597,6 @@ | Parameter 0 of RefreshColors | parameter | 32 | | Parameter 0 of RemoveFirstArgIfRelatedActivityId | parameter | 32 | | Parameter 0 of Resize | parameter | 32 | -| Parameter 0 of RhBulkMoveWithWriteBarrier | parameter | 32 | -| Parameter 0 of RhZeroMemory | parameter | 32 | | Parameter 0 of Round | parameter | 32 | | Parameter 0 of RoundNumber | parameter | 32 | | Parameter 0 of SearchScale | parameter | 32 | @@ -563,11 +606,23 @@ | Parameter 0 of SetDateMDY | parameter | 32 | | Parameter 0 of SetDateYDM | parameter | 32 | | Parameter 0 of SetDateYMD | parameter | 32 | +| Parameter 0 of SetUInt32 | parameter | 32 | +| Parameter 0 of SetUInt64 | parameter | 32 | +| Parameter 0 of SetValue | parameter | 32 | +| Parameter 0 of SetZero | parameter | 32 | | Parameter 0 of Sign | parameter | 32 | +| Parameter 0 of SkipInit | parameter | 32 | | Parameter 0 of Start | parameter | 32 | +| Parameter 0 of StartAssemblyLoad | parameter | 32 | +| Parameter 0 of StelemRef_Helper | parameter | 32 | +| Parameter 0 of StelemRef_Helper_NoCacheLookup | parameter | 32 | +| Parameter 0 of StopAssemblyLoad | parameter | 32 | | Parameter 0 of SubtractDivisor | parameter | 32 | +| Parameter 0 of Swap | parameter | 32 | +| Parameter 0 of SwapIfGreater | parameter | 32 | | Parameter 0 of TZif_GenerateAdjustmentRule | parameter | 32 | | Parameter 0 of TZif_GenerateAdjustmentRules | parameter | 32 | +| Parameter 0 of TableMask | parameter | 32 | | Parameter 0 of TrimEventDescriptors | parameter | 32 | | Parameter 0 of Truncate | parameter | 32 | | Parameter 0 of TryAdjustYear | parameter | 32 | @@ -577,6 +632,7 @@ | Parameter 0 of TryFormatDecimalF | parameter | 32 | | Parameter 0 of TryFormatDecimalG | parameter | 32 | | Parameter 0 of TryFormatThrowFormatException | parameter | 32 | +| Parameter 0 of TryGetAppLocalIcuSwitchValue | parameter | 32 | | Parameter 0 of TryGetCachedCursorPosition | parameter | 32 | | Parameter 0 of TryGetCursorPosition | parameter | 32 | | Parameter 0 of TryGetLocalTzFile | parameter | 32 | @@ -611,16 +667,23 @@ | Parameter 0 of VolatileWrite | parameter | 32 | | Parameter 0 of WidenFourAsciiBytesToUtf16AndWriteToBuffer | parameter | 32 | | Parameter 0 of Write | parameter | 32 | +| Parameter 0 of WriteBarrier | parameter | 32 | | Parameter 0 of WriteFirstUtf16CharAsUtf8ThreeByteSequence | parameter | 32 | | Parameter 0 of WriteNibble | parameter | 32 | | Parameter 0 of WriteThreeLowOrderBytes | parameter | 32 | | Parameter 0 of WriteTwoUtf16CharsAsTwoUtf8ThreeByteSequences | parameter | 32 | | Parameter 0 of WriteUnaligned | parameter | 32 | +| Parameter 0 of _BulkMoveWithWriteBarrier | parameter | 32 | | Parameter 0 of _GetCurrentMethod | parameter | 32 | | Parameter 0 of _Memmove | parameter | 32 | +| Parameter 0 of _ZeroMemory | parameter | 32 | +| Parameter 0 of __BulkMoveWithWriteBarrier | parameter | 32 | | Parameter 1 of .ctor | parameter | 32 | -| Parameter 1 of b__21_0 | parameter | 32 | +| Parameter 1 of g__SoftwareFallback\|59_1 | parameter | 32 | +| Parameter 1 of g__SseImpl\|59_0 | parameter | 32 | +| Parameter 1 of g__Write\|65_0 | parameter | 32 | | Parameter 1 of AcquirePointer | parameter | 32 | +| Parameter 1 of AcquireSpan | parameter | 32 | | Parameter 1 of Add | parameter | 32 | | Parameter 1 of AddNonLetter | parameter | 32 | | Parameter 1 of AddSpecialInterface | parameter | 32 | @@ -631,8 +694,8 @@ | Parameter 1 of AreSame | parameter | 32 | | Parameter 1 of AwaitOnCompleted | parameter | 32 | | Parameter 1 of AwaitUnsafeOnCompleted | parameter | 32 | -| Parameter 1 of BeginInvoke | parameter | 32 | | Parameter 1 of Block | parameter | 32 | +| Parameter 1 of BulkMoveWithWriteBarrier | parameter | 32 | | Parameter 1 of ByteOffset | parameter | 32 | | Parameter 1 of ChangeCaseCommon | parameter | 32 | | Parameter 1 of CheckDefaultDateTime | parameter | 32 | @@ -640,6 +703,7 @@ | Parameter 1 of CheckVMForIOPacket | parameter | 32 | | Parameter 1 of ClearManaged | parameter | 32 | | Parameter 1 of ClearNative | parameter | 32 | +| Parameter 1 of ClearNativeContents | parameter | 32 | | Parameter 1 of Clone | parameter | 32 | | Parameter 1 of Compare | parameter | 32 | | Parameter 1 of ConfigureFormatOS | parameter | 32 | @@ -649,6 +713,8 @@ | Parameter 1 of ConvertContentsToManaged | parameter | 32 | | Parameter 1 of ConvertContentsToNative | parameter | 32 | | Parameter 1 of ConvertGregorianToHijri | parameter | 32 | +| Parameter 1 of ConvertSafeHandleToNative | parameter | 32 | +| Parameter 1 of ConvertSmpToUtf16 | parameter | 32 | | Parameter 1 of ConvertSpaceToManaged | parameter | 32 | | Parameter 1 of ConvertSpaceToNative | parameter | 32 | | Parameter 1 of CopyRuntimeTypeHandles | parameter | 32 | @@ -664,15 +730,17 @@ | Parameter 1 of DecodeFromUtf16 | parameter | 32 | | Parameter 1 of DecodeLastFromUtf8 | parameter | 32 | | Parameter 1 of DecodeLastFromUtf16 | parameter | 32 | +| Parameter 1 of Decompose | parameter | 32 | | Parameter 1 of Deconstruct | parameter | 32 | | Parameter 1 of Div96ByConst | parameter | 32 | | Parameter 1 of Div128By96 | parameter | 32 | | Parameter 1 of DivRem | parameter | 32 | +| Parameter 1 of DivRem32 | parameter | 32 | | Parameter 1 of EatWhiteSpace | parameter | 32 | | Parameter 1 of Encode | parameter | 32 | +| Parameter 1 of EncodeHexString | parameter | 32 | | Parameter 1 of EncodeObject | parameter | 32 | | Parameter 1 of EncodeTags | parameter | 32 | -| Parameter 1 of EndInvoke | parameter | 32 | | Parameter 1 of EnsureInitialized | parameter | 32 | | Parameter 1 of EnsureInitializedCore | parameter | 32 | | Parameter 1 of Enter | parameter | 32 | @@ -680,8 +748,7 @@ | Parameter 1 of EnumConnections | parameter | 32 | | Parameter 1 of EnumObjectParam | parameter | 32 | | Parameter 1 of EnumRunning | parameter | 32 | -| Parameter 1 of EqualsOrdinalIgnoreCase | parameter | 32 | -| Parameter 1 of EqualsOrdinalIgnoreCaseNonAscii | parameter | 32 | +| Parameter 1 of EqualsIgnoreCase | parameter | 32 | | Parameter 1 of EtwEnableCallBack | parameter | 32 | | Parameter 1 of EvaluateInternal | parameter | 32 | | Parameter 1 of EventActivityIdControl | parameter | 32 | @@ -691,7 +758,6 @@ | Parameter 1 of FStat | parameter | 32 | | Parameter 1 of FilterCustomAttributeRecord | parameter | 32 | | Parameter 1 of FilterHelper | parameter | 32 | -| Parameter 1 of FindAndParseNextNumber | parameter | 32 | | Parameter 1 of FindConnectionPoint | parameter | 32 | | Parameter 1 of FormatCurrency | parameter | 32 | | Parameter 1 of FormatFixed | parameter | 32 | @@ -714,10 +780,10 @@ | Parameter 1 of GetContainingTypeLib | parameter | 32 | | Parameter 1 of GetCurFile | parameter | 32 | | Parameter 1 of GetCustData | parameter | 32 | +| Parameter 1 of GetDate | parameter | 32 | | Parameter 1 of GetDateOfDSN | parameter | 32 | | Parameter 1 of GetDateOfNDS | parameter | 32 | | Parameter 1 of GetDateOfNNDS | parameter | 32 | -| Parameter 1 of GetDatePart | parameter | 32 | | Parameter 1 of GetDateTimeNow | parameter | 32 | | Parameter 1 of GetDateTimeNowUtcOffsetFromUtc | parameter | 32 | | Parameter 1 of GetDayOfMN | parameter | 32 | @@ -737,10 +803,12 @@ | Parameter 1 of GetFloatingPointMaxDigitsAndPrecision | parameter | 32 | | Parameter 1 of GetGUID | parameter | 32 | | Parameter 1 of GetHebrewDayOfNM | parameter | 32 | +| Parameter 1 of GetIUnknownImpl | parameter | 32 | | Parameter 1 of GetInterface | parameter | 32 | | Parameter 1 of GetJapaneseEraStartDate | parameter | 32 | | Parameter 1 of GetJitContext | parameter | 32 | | Parameter 1 of GetLibAttr | parameter | 32 | +| Parameter 1 of GetLicInfo | parameter | 32 | | Parameter 1 of GetLocalSignature | parameter | 32 | | Parameter 1 of GetLocaleName | parameter | 32 | | Parameter 1 of GetMarshalAs | parameter | 32 | @@ -748,17 +816,19 @@ | Parameter 1 of GetMaxThreadsNative | parameter | 32 | | Parameter 1 of GetMemberCache | parameter | 32 | | Parameter 1 of GetMemberList | parameter | 32 | -| Parameter 1 of GetMemoryInfo | parameter | 32 | -| Parameter 1 of GetMetadata | parameter | 32 | +| Parameter 1 of GetMetadataLength | parameter | 32 | +| Parameter 1 of GetMetadataLengthForTypeV2 | parameter | 32 | +| Parameter 1 of GetMetadataLengthV2 | parameter | 32 | | Parameter 1 of GetMinThreads | parameter | 32 | | Parameter 1 of GetMinThreadsNative | parameter | 32 | +| Parameter 1 of GetMonthDayOrder | parameter | 32 | | Parameter 1 of GetNeutralResourcesLanguage | parameter | 32 | +| Parameter 1 of GetNextUnicodeScalarValueFromUtf16Surrogate | parameter | 32 | | Parameter 1 of GetObjectStartLength | parameter | 32 | | Parameter 1 of GetPEKind | parameter | 32 | | Parameter 1 of GetPrimaryAndSecondary | parameter | 32 | | Parameter 1 of GetPropertyOrFieldData | parameter | 32 | | Parameter 1 of GetPwUidR | parameter | 32 | -| Parameter 1 of GetRawArrayGeometry | parameter | 32 | | Parameter 1 of GetRegularToken | parameter | 32 | | Parameter 1 of GetRunningObjectTable | parameter | 32 | | Parameter 1 of GetScopeProps | parameter | 32 | @@ -766,39 +836,47 @@ | Parameter 1 of GetSortHandle | parameter | 32 | | Parameter 1 of GetStackTracesDeepCopy | parameter | 32 | | Parameter 1 of GetStateMachineBox | parameter | 32 | +| Parameter 1 of GetTime | parameter | 32 | | Parameter 1 of GetTimeOfN | parameter | 32 | | Parameter 1 of GetTimeOfNN | parameter | 32 | | Parameter 1 of GetTimeOfNNN | parameter | 32 | +| Parameter 1 of GetTimePrecise | parameter | 32 | | Parameter 1 of GetTypeAttr | parameter | 32 | | Parameter 1 of GetTypeComp | parameter | 32 | | Parameter 1 of GetTypeFlags | parameter | 32 | +| Parameter 1 of GetTypeInfoFromType | parameter | 32 | | Parameter 1 of GetTypeInfoOfGuid | parameter | 32 | | Parameter 1 of GetTypeKind | parameter | 32 | | Parameter 1 of GetUtf16SurrogatesFromSupplementaryPlaneScalar | parameter | 32 | | Parameter 1 of GetVersion | parameter | 32 | | Parameter 1 of GetWindowSize | parameter | 32 | -| Parameter 1 of GrowTable | parameter | 32 | +| Parameter 1 of GetYearMonthDayOrder | parameter | 32 | +| Parameter 1 of GetYearMonthOrder | parameter | 32 | +| Parameter 1 of GreaterThan | parameter | 32 | | Parameter 1 of HandleTimeZone | parameter | 32 | | Parameter 1 of Hash | parameter | 32 | | Parameter 1 of HeuristicDivide | parameter | 32 | +| Parameter 1 of HtmlDecode | parameter | 32 | +| Parameter 1 of HtmlEncode | parameter | 32 | | Parameter 1 of Initialize | parameter | 32 | | Parameter 1 of Insert | parameter | 32 | | Parameter 1 of Int32ToNumber | parameter | 32 | | Parameter 1 of Int64ToNumber | parameter | 32 | | Parameter 1 of InternalGetSignature | parameter | 32 | | Parameter 1 of InternalLoad | parameter | 32 | -| Parameter 1 of InternalLoadAssemblyName | parameter | 32 | | Parameter 1 of InternalTryGetRawMetadata | parameter | 32 | | Parameter 1 of Inverse | parameter | 32 | +| Parameter 1 of Invert | parameter | 32 | | Parameter 1 of Invoke | parameter | 32 | | Parameter 1 of IsAddressGreaterThan | parameter | 32 | | Parameter 1 of IsAddressLessThan | parameter | 32 | | Parameter 1 of IsSystemMoniker | parameter | 32 | | Parameter 1 of LStat | parameter | 32 | | Parameter 1 of LazyCreateEvent | parameter | 32 | +| Parameter 1 of LessThan | parameter | 32 | | Parameter 1 of Lex | parameter | 32 | -| Parameter 1 of Load | parameter | 32 | | Parameter 1 of MapBufferToConsoleKey | parameter | 32 | +| Parameter 1 of MarshalToNative | parameter | 32 | | Parameter 1 of Max | parameter | 32 | | Parameter 1 of Memmove | parameter | 32 | | Parameter 1 of Min | parameter | 32 | @@ -836,18 +914,23 @@ | Parameter 1 of ReorderArgumentArray | parameter | 32 | | Parameter 1 of ReplaceInPlaceAtChunk | parameter | 32 | | Parameter 1 of RestoreDispatchState | parameter | 32 | -| Parameter 1 of RhBulkMoveWithWriteBarrier | parameter | 32 | | Parameter 1 of SafeHandleAddRef | parameter | 32 | | Parameter 1 of SequenceEqual | parameter | 32 | +| Parameter 1 of SerializeSubstitute | parameter | 32 | +| Parameter 1 of SerializeTransitionTime | parameter | 32 | | Parameter 1 of SetBindOptions | parameter | 32 | | Parameter 1 of SetCurrentThreadActivityId | parameter | 32 | +| Parameter 1 of SetException | parameter | 32 | +| Parameter 1 of SetNotificationForWaitCompletion | parameter | 32 | | Parameter 1 of SetValue | parameter | 32 | -| Parameter 1 of SkipWhitespace | parameter | 32 | | Parameter 1 of SnapForObservation | parameter | 32 | | Parameter 1 of SplitName | parameter | 32 | | Parameter 1 of Start | parameter | 32 | +| Parameter 1 of StartAssemblyLoad | parameter | 32 | | Parameter 1 of Stat | parameter | 32 | | Parameter 1 of Subtract | parameter | 32 | +| Parameter 1 of Swap | parameter | 32 | +| Parameter 1 of SwapIfGreater | parameter | 32 | | Parameter 1 of TZif_ParseJulianDay | parameter | 32 | | Parameter 1 of TZif_ParseMDateRule | parameter | 32 | | Parameter 1 of TZif_ParsePosixDate | parameter | 32 | @@ -864,6 +947,7 @@ | Parameter 1 of TryDequeueSlow | parameter | 32 | | Parameter 1 of TryDigitGenShortest | parameter | 32 | | Parameter 1 of TryEnter | parameter | 32 | +| Parameter 1 of TryFindFirstMatchedLane | parameter | 32 | | Parameter 1 of TryGetArray | parameter | 32 | | Parameter 1 of TryGetBuffer | parameter | 32 | | Parameter 1 of TryGetCachedCursorPosition | parameter | 32 | @@ -898,6 +982,7 @@ | Parameter 1 of TryParseExactP | parameter | 32 | | Parameter 1 of TryParseExactX | parameter | 32 | | Parameter 1 of TryParseGuid | parameter | 32 | +| Parameter 1 of TryParseGuidCore | parameter | 32 | | Parameter 1 of TryParseGuidN | parameter | 32 | | Parameter 1 of TryParseHebrewNumber | parameter | 32 | | Parameter 1 of TryParseHex | parameter | 32 | @@ -928,12 +1013,16 @@ | Parameter 1 of TryParseUInt64X | parameter | 32 | | Parameter 1 of TryPeek | parameter | 32 | | Parameter 1 of TryRead | parameter | 32 | +| Parameter 1 of TryReadDoubleBigEndian | parameter | 32 | +| Parameter 1 of TryReadDoubleLittleEndian | parameter | 32 | | Parameter 1 of TryReadInt16BigEndian | parameter | 32 | | Parameter 1 of TryReadInt16LittleEndian | parameter | 32 | | Parameter 1 of TryReadInt32BigEndian | parameter | 32 | | Parameter 1 of TryReadInt32LittleEndian | parameter | 32 | | Parameter 1 of TryReadInt64BigEndian | parameter | 32 | | Parameter 1 of TryReadInt64LittleEndian | parameter | 32 | +| Parameter 1 of TryReadSingleBigEndian | parameter | 32 | +| Parameter 1 of TryReadSingleLittleEndian | parameter | 32 | | Parameter 1 of TryReadUInt16BigEndian | parameter | 32 | | Parameter 1 of TryReadUInt16LittleEndian | parameter | 32 | | Parameter 1 of TryReadUInt32BigEndian | parameter | 32 | @@ -948,8 +1037,6 @@ | Parameter 1 of UInt32ToNumber | parameter | 32 | | Parameter 1 of UInt64ToNumber | parameter | 32 | | Parameter 1 of Unscale | parameter | 32 | -| Parameter 1 of ValidateEventOpcodeForTransfer | parameter | 32 | -| Parameter 1 of ValidateVariableAndValue | parameter | 32 | | Parameter 1 of VarDecCmp | parameter | 32 | | Parameter 1 of VarDecCmpSub | parameter | 32 | | Parameter 1 of VarDecDiv | parameter | 32 | @@ -963,13 +1050,16 @@ | Parameter 1 of WriteEvent | parameter | 32 | | Parameter 1 of WriteEventRaw | parameter | 32 | | Parameter 1 of YearMonthAdjustment | parameter | 32 | +| Parameter 1 of _BulkMoveWithWriteBarrier | parameter | 32 | | Parameter 1 of _GetScopeProps | parameter | 32 | | Parameter 1 of _Memmove | parameter | 32 | -| Parameter 1 of nCreateDynamicAssembly | parameter | 32 | +| Parameter 1 of __BulkMoveWithWriteBarrier | parameter | 32 | | Parameter 1 of nGetPrimaryAndSecondary | parameter | 32 | -| Parameter 2 of g__BufferUntil\|86_0 | parameter | 32 | +| Parameter 2 of g__SoftwareFallback\|42_0 | parameter | 32 | +| Parameter 2 of g__BufferUntil\|83_0 | parameter | 32 | | Parameter 2 of Add | parameter | 32 | | Parameter 2 of AddDivisor | parameter | 32 | +| Parameter 2 of AddIfNotPresent | parameter | 32 | | Parameter 2 of AddNum | parameter | 32 | | Parameter 2 of AddResourceSet | parameter | 32 | | Parameter 2 of AddSep | parameter | 32 | @@ -979,15 +1069,18 @@ | Parameter 2 of AttributeUsageCheck | parameter | 32 | | Parameter 2 of AwaitOnCompleted | parameter | 32 | | Parameter 2 of AwaitUnsafeOnCompleted | parameter | 32 | +| Parameter 2 of BigMul | parameter | 32 | | Parameter 2 of BiggestPowerTen | parameter | 32 | | Parameter 2 of ChangeCaseCommon | parameter | 32 | | Parameter 2 of CheckVMForIOPacket | parameter | 32 | | Parameter 2 of CommonPrefixWith | parameter | 32 | -| Parameter 2 of CompareOrdinalIgnoreCase | parameter | 32 | -| Parameter 2 of CompareStringOrdinalIgnoreCase | parameter | 32 | +| Parameter 2 of CompareIgnoreCaseInvariantMode | parameter | 32 | +| Parameter 2 of CompareStringIgnoreCase | parameter | 32 | +| Parameter 2 of CompareStringIgnoreCaseNonAscii | parameter | 32 | | Parameter 2 of ConfigureFormatR | parameter | 32 | | Parameter 2 of ContinueTryEnter | parameter | 32 | | Parameter 2 of ConvertGregorianToHijri | parameter | 32 | +| Parameter 2 of ConvertSmpToUtf16 | parameter | 32 | | Parameter 2 of ConvertUtcToTimeZone | parameter | 32 | | Parameter 2 of CopyToTempBufferWithoutWhiteSpace | parameter | 32 | | Parameter 2 of CountOccurrences | parameter | 32 | @@ -1000,6 +1093,7 @@ | Parameter 2 of DecodeFromUtf16 | parameter | 32 | | Parameter 2 of DecodeLastFromUtf8 | parameter | 32 | | Parameter 2 of DecodeLastFromUtf16 | parameter | 32 | +| Parameter 2 of Decompose | parameter | 32 | | Parameter 2 of Deconstruct | parameter | 32 | | Parameter 2 of Dequeue | parameter | 32 | | Parameter 2 of DivByConst | parameter | 32 | @@ -1008,7 +1102,6 @@ | Parameter 2 of DrainLeftoverDataForGetByteCount | parameter | 32 | | Parameter 2 of DrainLeftoverDataForGetCharCount | parameter | 32 | | Parameter 2 of EncodeObject | parameter | 32 | -| Parameter 2 of EndInvoke | parameter | 32 | | Parameter 2 of EnqueueSlow | parameter | 32 | | Parameter 2 of EnsureInitialized | parameter | 32 | | Parameter 2 of EnsureInitializedCore | parameter | 32 | @@ -1030,6 +1123,8 @@ | Parameter 2 of FromUtf16 | parameter | 32 | | Parameter 2 of GenerateMetadata | parameter | 32 | | Parameter 2 of GenerateMetadataForProperty | parameter | 32 | +| Parameter 2 of GenerateMetadataForTypeV2 | parameter | 32 | +| Parameter 2 of GenerateMetadataV2 | parameter | 32 | | Parameter 2 of GetAdjustmentRuleForAmbiguousOffsets | parameter | 32 | | Parameter 2 of GetAdjustmentRuleForTime | parameter | 32 | | Parameter 2 of GetBoundaries | parameter | 32 | @@ -1037,15 +1132,15 @@ | Parameter 2 of GetClassLayout | parameter | 32 | | Parameter 2 of GetCodeInfo | parameter | 32 | | Parameter 2 of GetContainingTypeLib | parameter | 32 | +| Parameter 2 of GetCurrentContextInfo | parameter | 32 | | Parameter 2 of GetCustData | parameter | 32 | | Parameter 2 of GetCustomAttributeProps | parameter | 32 | | Parameter 2 of GetCustomAttributes | parameter | 32 | -| Parameter 2 of GetDatePart | parameter | 32 | +| Parameter 2 of GetDate | parameter | 32 | | Parameter 2 of GetDayOfMN | parameter | 32 | | Parameter 2 of GetDayOfNM | parameter | 32 | | Parameter 2 of GetDayOfNN | parameter | 32 | | Parameter 2 of GetDefaultValue | parameter | 32 | -| Parameter 2 of GetDisplayName | parameter | 32 | | Parameter 2 of GetDocumentation | parameter | 32 | | Parameter 2 of GetDocumentation2 | parameter | 32 | | Parameter 2 of GetDynamicOrStaticVariables | parameter | 32 | @@ -1057,6 +1152,7 @@ | Parameter 2 of GetFuncCustData | parameter | 32 | | Parameter 2 of GetFuncDesc | parameter | 32 | | Parameter 2 of GetGenericParamProps | parameter | 32 | +| Parameter 2 of GetIUnknownImpl | parameter | 32 | | Parameter 2 of GetImplTypeCustData | parameter | 32 | | Parameter 2 of GetImplTypeFlags | parameter | 32 | | Parameter 2 of GetIndexOfNextTokenAfterSeconds | parameter | 32 | @@ -1067,9 +1163,7 @@ | Parameter 2 of GetLocaleInfoGroupingSizes | parameter | 32 | | Parameter 2 of GetLocaleInfoInt | parameter | 32 | | Parameter 2 of GetMarshalAs | parameter | 32 | -| Parameter 2 of GetMemoryInfo | parameter | 32 | -| Parameter 2 of GetMetadata | parameter | 32 | -| Parameter 2 of GetMonthDayOrder | parameter | 32 | +| Parameter 2 of GetMetadataLengthForNamedTypeV2 | parameter | 32 | | Parameter 2 of GetMops | parameter | 32 | | Parameter 2 of GetObject | parameter | 32 | | Parameter 2 of GetObjectParam | parameter | 32 | @@ -1080,7 +1174,6 @@ | Parameter 2 of GetPointerToFirstInvalidByte | parameter | 32 | | Parameter 2 of GetPointerToFirstInvalidChar | parameter | 32 | | Parameter 2 of GetPropertyProps | parameter | 32 | -| Parameter 2 of GetRawArrayGeometry | parameter | 32 | | Parameter 2 of GetRefTypeInfo | parameter | 32 | | Parameter 2 of GetRefTypeOfImplType | parameter | 32 | | Parameter 2 of GetRegularToken | parameter | 32 | @@ -1090,11 +1183,14 @@ | Parameter 2 of GetSessionInfo | parameter | 32 | | Parameter 2 of GetSessionInfoCallback | parameter | 32 | | Parameter 2 of GetStackTracesDeepCopy | parameter | 32 | +| Parameter 2 of GetTime | parameter | 32 | | Parameter 2 of GetTimeOfLastChange | parameter | 32 | +| Parameter 2 of GetTimePrecise | parameter | 32 | | Parameter 2 of GetTypeInfo | parameter | 32 | | Parameter 2 of GetTypeInfoOfGuid | parameter | 32 | | Parameter 2 of GetTypeInfoType | parameter | 32 | | Parameter 2 of GetUnescapeSequence | parameter | 32 | +| Parameter 2 of GetUnicodeCategoryInternal | parameter | 32 | | Parameter 2 of GetUtcOffsetFromUniversalTime | parameter | 32 | | Parameter 2 of GetUtcOffsetFromUtc | parameter | 32 | | Parameter 2 of GetUtf16SurrogatesFromSupplementaryPlaneScalar | parameter | 32 | @@ -1102,19 +1198,17 @@ | Parameter 2 of GetVarDesc | parameter | 32 | | Parameter 2 of GetVarIndexOfMemId | parameter | 32 | | Parameter 2 of GetVersion | parameter | 32 | -| Parameter 2 of GetYearMonthDayOrder | parameter | 32 | -| Parameter 2 of GetYearMonthOrder | parameter | 32 | | Parameter 2 of GrabInts | parameter | 32 | | Parameter 2 of GrabLongs | parameter | 32 | | Parameter 2 of IndexOf | parameter | 32 | | Parameter 2 of IndexOfAny | parameter | 32 | | Parameter 2 of Initialize | parameter | 32 | -| Parameter 2 of InternalConvertToUtf32 | parameter | 32 | | Parameter 2 of InternalDefineDynamicAssembly | parameter | 32 | | Parameter 2 of InternalFallback | parameter | 32 | | Parameter 2 of InternalFallbackGetByteCount | parameter | 32 | -| Parameter 2 of InternalGetUnicodeCategory | parameter | 32 | +| Parameter 2 of InternalLoad | parameter | 32 | | Parameter 2 of InternalTryGetRawMetadata | parameter | 32 | +| Parameter 2 of Invoke | parameter | 32 | | Parameter 2 of IsDigit | parameter | 32 | | Parameter 2 of IsInstanceOfInterface | parameter | 32 | | Parameter 2 of LastIndexOf | parameter | 32 | @@ -1143,7 +1237,6 @@ | Parameter 2 of ParseComponent | parameter | 32 | | Parameter 2 of ParseDigits | parameter | 32 | | Parameter 2 of ParseExactDigits | parameter | 32 | -| Parameter 2 of ParseFormatO | parameter | 32 | | Parameter 2 of ParseFormatR | parameter | 32 | | Parameter 2 of ParseFractionExact | parameter | 32 | | Parameter 2 of ParseInt | parameter | 32 | @@ -1167,11 +1260,10 @@ | Parameter 2 of Remove | parameter | 32 | | Parameter 2 of RemoveRelativeSegments | parameter | 32 | | Parameter 2 of ReplaceInPlaceAtChunk | parameter | 32 | +| Parameter 2 of RequestLicKey | parameter | 32 | | Parameter 2 of ResolveToken | parameter | 32 | | Parameter 2 of RunForThreadPoolUnsafe | parameter | 32 | -| Parameter 2 of RunInternal | parameter | 32 | | Parameter 2 of SequenceCompareTo | parameter | 32 | -| Parameter 2 of ShiftLeft | parameter | 32 | | Parameter 2 of SnapForObservation | parameter | 32 | | Parameter 2 of SplitName | parameter | 32 | | Parameter 2 of SubtractDivisor | parameter | 32 | @@ -1181,6 +1273,7 @@ | Parameter 2 of TZif_ParsePosixFormat | parameter | 32 | | Parameter 2 of TZif_ParseRaw | parameter | 32 | | Parameter 2 of TimeToLunar | parameter | 32 | +| Parameter 2 of ToUpperSurrogate | parameter | 32 | | Parameter 2 of ToUtf16 | parameter | 32 | | Parameter 2 of Tokenize | parameter | 32 | | Parameter 2 of TryAddTicks | parameter | 32 | @@ -1195,6 +1288,7 @@ | Parameter 2 of TryEncodeToUtf8 | parameter | 32 | | Parameter 2 of TryEncodeToUtf16 | parameter | 32 | | Parameter 2 of TryEnter | parameter | 32 | +| Parameter 2 of TryFindFirstMatchedLane | parameter | 32 | | Parameter 2 of TryFormat | parameter | 32 | | Parameter 2 of TryFormatDateTimeL | parameter | 32 | | Parameter 2 of TryFormatDateTimeR | parameter | 32 | @@ -1202,20 +1296,15 @@ | Parameter 2 of TryFormatDecimalF | parameter | 32 | | Parameter 2 of TryFormatDecimalG | parameter | 32 | | Parameter 2 of TryFormatFloatingPoint | parameter | 32 | -| Parameter 2 of TryFormatInt32MultipleDigits | parameter | 32 | | Parameter 2 of TryFormatInt64Default | parameter | 32 | -| Parameter 2 of TryFormatInt64LessThanNegativeBillionMaxUInt | parameter | 32 | -| Parameter 2 of TryFormatInt64MoreThanNegativeBillionMaxUInt | parameter | 32 | | Parameter 2 of TryFormatInt64MultipleDigits | parameter | 32 | -| Parameter 2 of TryFormatUInt32MultipleDigits | parameter | 32 | | Parameter 2 of TryFormatUInt32SingleDigit | parameter | 32 | | Parameter 2 of TryFormatUInt64 | parameter | 32 | | Parameter 2 of TryFormatUInt64Default | parameter | 32 | -| Parameter 2 of TryFormatUInt64LessThanBillionMaxUInt | parameter | 32 | -| Parameter 2 of TryFormatUInt64MoreThanBillionMaxUInt | parameter | 32 | | Parameter 2 of TryFormatUInt64MultipleDigits | parameter | 32 | | Parameter 2 of TryFromBase64Chars | parameter | 32 | | Parameter 2 of TryFromBase64String | parameter | 32 | +| Parameter 2 of TryGetBits | parameter | 32 | | Parameter 2 of TryGetByteCount | parameter | 32 | | Parameter 2 of TryGetEntry | parameter | 32 | | Parameter 2 of TryGetExport | parameter | 32 | @@ -1224,9 +1313,9 @@ | Parameter 2 of TryGetRawMetadata | parameter | 32 | | Parameter 2 of TryGetRuneAt | parameter | 32 | | Parameter 2 of TryGetString | parameter | 32 | +| Parameter 2 of TryGetStringValue | parameter | 32 | | Parameter 2 of TryGetTimeZone | parameter | 32 | | Parameter 2 of TryGetTimeZoneFromLocalMachine | parameter | 32 | -| Parameter 2 of TryGetUserNameFromPasswd | parameter | 32 | | Parameter 2 of TryGetValue | parameter | 32 | | Parameter 2 of TryGetValueWorker | parameter | 32 | | Parameter 2 of TryLoadTzFile | parameter | 32 | @@ -1239,6 +1328,7 @@ | Parameter 2 of TryParseDateTimeOffsetO | parameter | 32 | | Parameter 2 of TryParseDateTimeOffsetR | parameter | 32 | | Parameter 2 of TryParseExact | parameter | 32 | +| Parameter 2 of TryParseGuidCore | parameter | 32 | | Parameter 2 of TryParseGuidN | parameter | 32 | | Parameter 2 of TryParseHebrewNumber | parameter | 32 | | Parameter 2 of TryParseHex | parameter | 32 | @@ -1252,6 +1342,7 @@ | Parameter 2 of TryParseNumber | parameter | 32 | | Parameter 2 of TryParseSByteD | parameter | 32 | | Parameter 2 of TryParseSByteN | parameter | 32 | +| Parameter 2 of TryParseThrowFormatException | parameter | 32 | | Parameter 2 of TryParseTimeSpanBigG | parameter | 32 | | Parameter 2 of TryParseTimeSpanC | parameter | 32 | | Parameter 2 of TryParseTimeSpanFraction | parameter | 32 | @@ -1268,6 +1359,7 @@ | Parameter 2 of TryParseUInt64N | parameter | 32 | | Parameter 2 of TryParseUInt64X | parameter | 32 | | Parameter 2 of TryRunDouble | parameter | 32 | +| Parameter 2 of TryRunHalf | parameter | 32 | | Parameter 2 of TryRunShortest | parameter | 32 | | Parameter 2 of TryRunSingle | parameter | 32 | | Parameter 2 of TryStringToNumber | parameter | 32 | @@ -1302,13 +1394,12 @@ | Parameter 2 of _ParseAttributeUsageAttribute | parameter | 32 | | Parameter 2 of ctor>g__TryConvertFromInvariantString\|2_0 | parameter | 32 | | Parameter 3 of .ctor | parameter | 32 | -| Parameter 3 of b__39_0 | parameter | 32 | -| Parameter 3 of g__AppendToStdInReaderUntil\|86_1 | parameter | 32 | -| Parameter 3 of g__BufferUntil\|86_0 | parameter | 32 | +| Parameter 3 of b__37_0 | parameter | 32 | +| Parameter 3 of g__AppendToStdInReaderUntil\|83_1 | parameter | 32 | +| Parameter 3 of g__BufferUntil\|83_0 | parameter | 32 | | Parameter 3 of AccumulateDecimalDigitsIntoBigInteger | parameter | 32 | | Parameter 3 of AddressOfMember | parameter | 32 | | Parameter 3 of AtomicStateUpdate | parameter | 32 | -| Parameter 3 of BeginInvoke | parameter | 32 | | Parameter 3 of BindToMethod | parameter | 32 | | Parameter 3 of BindToObject | parameter | 32 | | Parameter 3 of BindToStorage | parameter | 32 | @@ -1316,6 +1407,7 @@ | Parameter 3 of CheckNewValue | parameter | 32 | | Parameter 3 of CompareExchange | parameter | 32 | | Parameter 3 of ComposeWith | parameter | 32 | +| Parameter 3 of ComputeVtables | parameter | 32 | | Parameter 3 of ContinueTryEnterWithThreadTracking | parameter | 32 | | Parameter 3 of ConvertGregorianToHijri | parameter | 32 | | Parameter 3 of ConvertHijriToGregorian | parameter | 32 | @@ -1323,21 +1415,21 @@ | Parameter 3 of CopyToTempBufferWithoutWhiteSpace | parameter | 32 | | Parameter 3 of CreateCaObject | parameter | 32 | | Parameter 3 of CreateInstance | parameter | 32 | +| Parameter 3 of CreateInstanceLic | parameter | 32 | | Parameter 3 of CreateMutexCore | parameter | 32 | | Parameter 3 of DecodeFirstRune | parameter | 32 | | Parameter 3 of DecodeObject | parameter | 32 | +| Parameter 3 of Decompose | parameter | 32 | | Parameter 3 of Deconstruct | parameter | 32 | -| Parameter 3 of DefineDynamicModuleInternal | parameter | 32 | -| Parameter 3 of DefineDynamicModuleInternalNoLock | parameter | 32 | | Parameter 3 of DivByConst | parameter | 32 | | Parameter 3 of DivRem | parameter | 32 | | Parameter 3 of DoAnsiConversion | parameter | 32 | | Parameter 3 of Dragon4Double | parameter | 32 | +| Parameter 3 of Dragon4Half | parameter | 32 | | Parameter 3 of Dragon4Single | parameter | 32 | | Parameter 3 of DrainLeftoverDataForGetChars | parameter | 32 | | Parameter 3 of EncodeObject | parameter | 32 | | Parameter 3 of EncodeRune | parameter | 32 | -| Parameter 3 of EndInvoke | parameter | 32 | | Parameter 3 of Enum | parameter | 32 | | Parameter 3 of EnumCalendarInfo | parameter | 32 | | Parameter 3 of EnumDatePatterns | parameter | 32 | @@ -1346,16 +1438,17 @@ | Parameter 3 of ExpandPredefinedFormat | parameter | 32 | | Parameter 3 of FilterHelper | parameter | 32 | | Parameter 3 of FromUtf16 | parameter | 32 | +| Parameter 3 of GenerateMetadataForNamedTypeV2 | parameter | 32 | | Parameter 3 of GetAdjustmentRuleForTime | parameter | 32 | | Parameter 3 of GetBoundaries | parameter | 32 | | Parameter 3 of GetCalendarInfo | parameter | 32 | | Parameter 3 of GetClassLayout | parameter | 32 | | Parameter 3 of GetCodeInfo | parameter | 32 | | Parameter 3 of GetControlCharacters | parameter | 32 | -| Parameter 3 of GetCurrentTextElementLen | parameter | 32 | +| Parameter 3 of GetCurrentContextInfo | parameter | 32 | | Parameter 3 of GetCustomAttributeProps | parameter | 32 | | Parameter 3 of GetDataFromController | parameter | 32 | -| Parameter 3 of GetDatePart | parameter | 32 | +| Parameter 3 of GetDate | parameter | 32 | | Parameter 3 of GetDefaultValue | parameter | 32 | | Parameter 3 of GetDisplayName | parameter | 32 | | Parameter 3 of GetDocumentation | parameter | 32 | @@ -1371,8 +1464,6 @@ | Parameter 3 of GetKeyFromCharValue | parameter | 32 | | Parameter 3 of GetLocaleInfoGroupingSizes | parameter | 32 | | Parameter 3 of GetMarshalAs | parameter | 32 | -| Parameter 3 of GetMemoryInfo | parameter | 32 | -| Parameter 3 of GetMetadata | parameter | 32 | | Parameter 3 of GetPInvokeMap | parameter | 32 | | Parameter 3 of GetParamCustData | parameter | 32 | | Parameter 3 of GetParamDefProps | parameter | 32 | @@ -1381,10 +1472,11 @@ | Parameter 3 of GetPointerToFirstInvalidChar | parameter | 32 | | Parameter 3 of GetPropertyOrFieldData | parameter | 32 | | Parameter 3 of GetPropertyProps | parameter | 32 | -| Parameter 3 of GetRawArrayGeometry | parameter | 32 | | Parameter 3 of GetResourceData | parameter | 32 | | Parameter 3 of GetSeparatorToken | parameter | 32 | +| Parameter 3 of GetTime | parameter | 32 | | Parameter 3 of GetTimeOfLastChange | parameter | 32 | +| Parameter 3 of GetTimePrecise | parameter | 32 | | Parameter 3 of GetType | parameter | 32 | | Parameter 3 of GetTypeByName | parameter | 32 | | Parameter 3 of GetUtcOffsetFromUtc | parameter | 32 | @@ -1428,6 +1520,7 @@ | Parameter 3 of TZif_ParsePosixFormat | parameter | 32 | | Parameter 3 of TZif_ParseRaw | parameter | 32 | | Parameter 3 of TimeToLunar | parameter | 32 | +| Parameter 3 of ToUpperSurrogate | parameter | 32 | | Parameter 3 of ToUtf16 | parameter | 32 | | Parameter 3 of Tokenize | parameter | 32 | | Parameter 3 of TryDecodeFromUtf16 | parameter | 32 | @@ -1444,6 +1537,7 @@ | Parameter 3 of TryFormatR | parameter | 32 | | Parameter 3 of TryGetEntry | parameter | 32 | | Parameter 3 of TryGetMemoryManager | parameter | 32 | +| Parameter 3 of TryGetSpan | parameter | 32 | | Parameter 3 of TryGetSpecialConsoleKey | parameter | 32 | | Parameter 3 of TryGetString | parameter | 32 | | Parameter 3 of TryGetTimeZone | parameter | 32 | @@ -1460,6 +1554,7 @@ | Parameter 3 of TryParseDecimal | parameter | 32 | | Parameter 3 of TryParseDouble | parameter | 32 | | Parameter 3 of TryParseExact | parameter | 32 | +| Parameter 3 of TryParseHalf | parameter | 32 | | Parameter 3 of TryParseInt32 | parameter | 32 | | Parameter 3 of TryParseInt32IntegerStyle | parameter | 32 | | Parameter 3 of TryParseInt32Number | parameter | 32 | @@ -1484,6 +1579,7 @@ | Parameter 3 of ValidateTimeZoneInfo | parameter | 32 | | Parameter 3 of Write | parameter | 32 | | Parameter 3 of WriteFile | parameter | 32 | +| Parameter 3 of WriteToBuffer | parameter | 32 | | Parameter 3 of _Enum | parameter | 32 | | Parameter 3 of _GetClassLayout | parameter | 32 | | Parameter 3 of _GetCustomAttributeProps | parameter | 32 | @@ -1496,13 +1592,14 @@ | Parameter 3 of _GetPropertyProps | parameter | 32 | | Parameter 3 of _GetUserString | parameter | 32 | | Parameter 3 of _ParseAttributeUsageAttribute | parameter | 32 | -| Parameter 3 of nLoad | parameter | 32 | | Parameter 4 of .ctor | parameter | 32 | -| Parameter 4 of g__AppendToStdInReaderUntil\|86_1 | parameter | 32 | -| Parameter 4 of g__BufferUntil\|86_0 | parameter | 32 | -| Parameter 4 of g__ReadRowOrCol\|86_2 | parameter | 32 | +| Parameter 4 of g__TryFormatInt64Slow\|43_0 | parameter | 32 | +| Parameter 4 of g__TryFormatUInt32Slow\|41_0 | parameter | 32 | +| Parameter 4 of g__TryFormatUInt64Slow\|45_0 | parameter | 32 | +| Parameter 4 of g__AppendToStdInReaderUntil\|83_1 | parameter | 32 | +| Parameter 4 of g__BufferUntil\|83_0 | parameter | 32 | +| Parameter 4 of g__ReadRowOrCol\|83_2 | parameter | 32 | | Parameter 4 of AssignAssociates | parameter | 32 | -| Parameter 4 of BeginInvoke | parameter | 32 | | Parameter 4 of Bind | parameter | 32 | | Parameter 4 of BindToObject | parameter | 32 | | Parameter 4 of BindToStorage | parameter | 32 | @@ -1515,7 +1612,6 @@ | Parameter 4 of CreateSemaphoreCore | parameter | 32 | | Parameter 4 of Deconstruct | parameter | 32 | | Parameter 4 of DoStrictParse | parameter | 32 | -| Parameter 4 of EndInvoke | parameter | 32 | | Parameter 4 of EnumMonthNames | parameter | 32 | | Parameter 4 of EscapeString | parameter | 32 | | Parameter 4 of EvaluateInternal | parameter | 32 | @@ -1523,25 +1619,27 @@ | Parameter 4 of FilterHelper | parameter | 32 | | Parameter 4 of GetByteCountFast | parameter | 32 | | Parameter 4 of GetCharCountFast | parameter | 32 | -| Parameter 4 of GetCurrentTextElementLen | parameter | 32 | | Parameter 4 of GetDataFromController | parameter | 32 | | Parameter 4 of GetDefaultValue | parameter | 32 | | Parameter 4 of GetDocumentation | parameter | 32 | | Parameter 4 of GetDocumentation2 | parameter | 32 | | Parameter 4 of GetMarshalAs | parameter | 32 | -| Parameter 4 of GetMemoryInfo | parameter | 32 | -| Parameter 4 of GetMetadata | parameter | 32 | | Parameter 4 of GetNames | parameter | 32 | | Parameter 4 of GetPInvokeMap | parameter | 32 | | Parameter 4 of GetParamCustData | parameter | 32 | | Parameter 4 of GetPropertyOrFieldData | parameter | 32 | | Parameter 4 of GetPropertyProps | parameter | 32 | -| Parameter 4 of GetRawArrayGeometry | parameter | 32 | +| Parameter 4 of GetTime | parameter | 32 | +| Parameter 4 of GetTimePrecise | parameter | 32 | | Parameter 4 of GetValue | parameter | 32 | | Parameter 4 of GetVersion | parameter | 32 | | Parameter 4 of GregorianToLunar | parameter | 32 | +| Parameter 4 of IndexOf | parameter | 32 | | Parameter 4 of InitHash | parameter | 32 | | Parameter 4 of Invoke | parameter | 32 | +| Parameter 4 of IsPrefix | parameter | 32 | +| Parameter 4 of IsSuffix | parameter | 32 | +| Parameter 4 of LastIndexOf | parameter | 32 | | Parameter 4 of Lex | parameter | 32 | | Parameter 4 of LunarToGregorian | parameter | 32 | | Parameter 4 of MakeRoom | parameter | 32 | @@ -1554,8 +1652,7 @@ | Parameter 4 of ParseExactDigits | parameter | 32 | | Parameter 4 of ParseExactMultiple | parameter | 32 | | Parameter 4 of PopulateEvents | parameter | 32 | -| Parameter 4 of ProcessHebrewTerminalState | parameter | 32 | -| Parameter 4 of ProcessTerminalState | parameter | 32 | +| Parameter 4 of ReadFromBuffer | parameter | 32 | | Parameter 4 of Reduce | parameter | 32 | | Parameter 4 of Remove | parameter | 32 | | Parameter 4 of ResolveToken | parameter | 32 | @@ -1572,7 +1669,7 @@ | Parameter 4 of TryDrainLeftoverDataForGetBytes | parameter | 32 | | Parameter 4 of TryFormatDecimal | parameter | 32 | | Parameter 4 of TryFormatDouble | parameter | 32 | -| Parameter 4 of TryFormatInt32 | parameter | 32 | +| Parameter 4 of TryFormatHalf | parameter | 32 | | Parameter 4 of TryFormatInt64 | parameter | 32 | | Parameter 4 of TryFormatSingle | parameter | 32 | | Parameter 4 of TryFormatStandard | parameter | 32 | @@ -1595,13 +1692,9 @@ | Parameter 4 of TryParseExactMultiple | parameter | 32 | | Parameter 4 of TryParseExactMultipleTimeSpan | parameter | 32 | | Parameter 4 of TryParseExactTimeSpan | parameter | 32 | -| Parameter 4 of TryParseGuidCore | parameter | 32 | | Parameter 4 of TryParseNumber | parameter | 32 | | Parameter 4 of TryRunCounted | parameter | 32 | | Parameter 4 of TryRunShortest | parameter | 32 | -| Parameter 4 of TrySZBinarySearch | parameter | 32 | -| Parameter 4 of TrySZIndexOf | parameter | 32 | -| Parameter 4 of TrySZLastIndexOf | parameter | 32 | | Parameter 4 of UpdateDescriptor | parameter | 32 | | Parameter 4 of Write | parameter | 32 | | Parameter 4 of _GetDefaultValue | parameter | 32 | @@ -1609,14 +1702,15 @@ | Parameter 4 of _GetPropertyOrFieldData | parameter | 32 | | Parameter 4 of _GetPropertyProps | parameter | 32 | | Parameter 4 of _ParseAttributeUsageAttribute | parameter | 32 | +| Parameter 5 of g__TryFormatInt32Slow\|39_0 | parameter | 32 | | Parameter 5 of AssignAssociates | parameter | 32 | -| Parameter 5 of BeginInvoke | parameter | 32 | | Parameter 5 of Bind | parameter | 32 | | Parameter 5 of ConstructType | parameter | 32 | | Parameter 5 of Convert | parameter | 32 | | Parameter 5 of ConvertHijriToGregorian | parameter | 32 | | Parameter 5 of CreateCaObject | parameter | 32 | | Parameter 5 of CreateInstance | parameter | 32 | +| Parameter 5 of CreateInstanceLic | parameter | 32 | | Parameter 5 of Deconstruct | parameter | 32 | | Parameter 5 of EnsureDestinationSize | parameter | 32 | | Parameter 5 of EvaluateInternal | parameter | 32 | @@ -1628,7 +1722,6 @@ | Parameter 5 of GetDocumentation | parameter | 32 | | Parameter 5 of GetIsDaylightSavingsFromUtc | parameter | 32 | | Parameter 5 of GetMarshalAs | parameter | 32 | -| Parameter 5 of GetMemoryInfo | parameter | 32 | | Parameter 5 of GetPropertyOrFieldData | parameter | 32 | | Parameter 5 of GetType | parameter | 32 | | Parameter 5 of GregorianToLunar | parameter | 32 | @@ -1646,11 +1739,11 @@ | Parameter 5 of TranscodeToUtf8 | parameter | 32 | | Parameter 5 of TranscodeToUtf16 | parameter | 32 | | Parameter 5 of TryDigitGenShortest | parameter | 32 | +| Parameter 5 of TryFormatInt32 | parameter | 32 | | Parameter 5 of TryParseAsSpecialFloatingPoint | parameter | 32 | | Parameter 5 of TryParseByName | parameter | 32 | | Parameter 5 of TryParseExact | parameter | 32 | | Parameter 5 of TryParseExactMultiple | parameter | 32 | -| Parameter 5 of TryParseGuidCore | parameter | 32 | | Parameter 5 of TryParseInt64Enum | parameter | 32 | | Parameter 5 of TryParseRareEnum | parameter | 32 | | Parameter 5 of TryParseUInt64Enum | parameter | 32 | @@ -1660,7 +1753,6 @@ | Parameter 5 of _GetMarshalAs | parameter | 32 | | Parameter 5 of _GetPropertyOrFieldData | parameter | 32 | | Parameter 6 of AssignAssociates | parameter | 32 | -| Parameter 6 of BeginInvoke | parameter | 32 | | Parameter 6 of Bind | parameter | 32 | | Parameter 6 of Convert | parameter | 32 | | Parameter 6 of Deconstruct | parameter | 32 | @@ -1703,7 +1795,6 @@ | Parameter 8 of TryParseInt32Enum | parameter | 32 | | Parameter 8 of _GetMarshalAs | parameter | 32 | | Parameter 9 of AssignAssociates | parameter | 32 | -| Parameter 9 of BeginInvoke | parameter | 32 | | Parameter 9 of Convert | parameter | 32 | | Parameter 9 of Deconstruct | parameter | 32 | | Parameter 9 of FilterCustomAttributeRecord | parameter | 32 | @@ -1712,15 +1803,12 @@ | Parameter 9 of TryToDateTime | parameter | 32 | | Parameter 9 of _GetMarshalAs | parameter | 32 | | Parameter 10 of AssignAssociates | parameter | 32 | -| Parameter 10 of BeginInvoke | parameter | 32 | | Parameter 10 of Convert | parameter | 32 | | Parameter 10 of Deconstruct | parameter | 32 | -| Parameter 10 of FilterCustomAttributeRecord | parameter | 32 | | Parameter 10 of Invoke | parameter | 32 | | Parameter 10 of TryCreateDateTimeOffset | parameter | 32 | | Parameter 10 of _GetMarshalAs | parameter | 32 | | Parameter 11 of AssignAssociates | parameter | 32 | -| Parameter 11 of BeginInvoke | parameter | 32 | | Parameter 11 of Deconstruct | parameter | 32 | | Parameter 11 of Invoke | parameter | 32 | | Parameter 12 of Deconstruct | parameter | 32 | @@ -1733,6 +1821,10 @@ | Parameter 19 of Deconstruct | parameter | 32 | | Parameter 20 of Deconstruct | parameter | 32 | | Parameter 21 of Deconstruct | parameter | 32 | +| TableData | method | 32 | +| ThrowArrayMismatchException | method | 32 | +| Unbox | method | 32 | +| Unbox_Helper | method | 32 | | get_Current | method | 32 | | get_EventHandle | method | 32 | | get_Item | method | 32 | diff --git a/csharp/ql/test/library-tests/cil/typeAnnotations/typeAnnotations.ql b/csharp/ql/test/library-tests/cil/typeAnnotations/typeAnnotations.ql index 6544f049f7c..e35b46f673d 100644 --- a/csharp/ql/test/library-tests/cil/typeAnnotations/typeAnnotations.ql +++ b/csharp/ql/test/library-tests/cil/typeAnnotations/typeAnnotations.ql @@ -21,5 +21,11 @@ private string elementType(Element e) { } from Element e, int i -where cil_type_annotation(e, i) +where + cil_type_annotation(e, i) and + ( + not e instanceof Parameter or + e.(Parameter).getDeclaringElement().(Method).getDeclaringType().getQualifiedName() != + "System.Environment" // There are OS specific methods in this class + ) select e.toString(), elementType(e), i diff --git a/csharp/ql/test/library-tests/commons/TargetFramework/HasElement.ql b/csharp/ql/test/library-tests/commons/TargetFramework/HasElement.ql index 1a0194bb901..50057df4904 100644 --- a/csharp/ql/test/library-tests/commons/TargetFramework/HasElement.ql +++ b/csharp/ql/test/library-tests/commons/TargetFramework/HasElement.ql @@ -2,5 +2,5 @@ import csharp import semmle.code.csharp.commons.TargetFramework from TargetFrameworkAttribute target, Class c -where target.hasElement(c) +where target.hasElement(c) and target.fromSource() select c, target diff --git a/csharp/ql/test/library-tests/commons/TargetFramework/NetCore.ql b/csharp/ql/test/library-tests/commons/TargetFramework/NetCore.ql index 486dcf8491d..9ec6896629f 100644 --- a/csharp/ql/test/library-tests/commons/TargetFramework/NetCore.ql +++ b/csharp/ql/test/library-tests/commons/TargetFramework/NetCore.ql @@ -2,5 +2,5 @@ import csharp import semmle.code.csharp.commons.TargetFramework from TargetFrameworkAttribute target -where target.isNetCore() +where target.isNetCore() and target.fromSource() select target diff --git a/csharp/ql/test/library-tests/commons/TargetFramework/TargetFrameworks.ql b/csharp/ql/test/library-tests/commons/TargetFramework/TargetFrameworks.ql index eefc403351f..85adee6a0a0 100644 --- a/csharp/ql/test/library-tests/commons/TargetFramework/TargetFrameworks.ql +++ b/csharp/ql/test/library-tests/commons/TargetFramework/TargetFrameworks.ql @@ -2,4 +2,5 @@ import csharp import semmle.code.csharp.commons.TargetFramework from TargetFrameworkAttribute target +where target.fromSource() select target, target.getFrameworkType(), target.getFrameworkVersion() diff --git a/csharp/ql/test/library-tests/csharp8/NameResolutionSuppressNullable.cs b/csharp/ql/test/library-tests/csharp8/NameResolutionSuppressNullable.cs new file mode 100644 index 00000000000..c1b84d940bc --- /dev/null +++ b/csharp/ql/test/library-tests/csharp8/NameResolutionSuppressNullable.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Threading; + +class MyClass2 +{ + private static WaitCallback? s_signalMethod; + private static WaitCallback SignalMethod => EnsureInitialized(ref s_signalMethod, () => new WaitCallback(M1!)); + + public static T EnsureInitialized(ref T target, System.Func valueFactory) where T : class { return target = valueFactory(); } + + static void M1(object state) + { + } +} diff --git a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected index 9d418a70ca0..ce6192ead71 100644 --- a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected +++ b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected @@ -1,4 +1,5 @@ suppressNullableWarnings +| NameResolutionSuppressNullable.cs:8:110:8:112 | ...! | NameResolutionSuppressNullable.cs:8:110:8:111 | access to method M1 | | NullableRefTypes.cs:85:20:85:21 | ...! | NullableRefTypes.cs:85:20:85:20 | access to local variable x | | NullableRefTypes.cs:86:13:86:14 | ...! | NullableRefTypes.cs:86:13:86:13 | access to local variable x | | NullableRefTypes.cs:88:13:88:14 | ...! | NullableRefTypes.cs:88:13:88:13 | access to local variable x | @@ -206,6 +207,7 @@ returnTypes | NullableRefTypes.cs:215:10:215:20 | ElementTest | Void! | | NullableRefTypes.cs:223:48:223:54 | GetSelf | TestNullableFlowStates? | methodTypeArguments +| NameResolutionSuppressNullable.cs:10:21:10:40 | EnsureInitialized | 0 | WaitCallback? | | NullableRefTypes.cs:51:12:51:15 | Q | 0 | MyClass! | | NullableRefTypes.cs:51:12:51:15 | Q | 0 | MyClass? | | NullableRefTypes.cs:67:10:67:21 | GenericFn | 0 | MyClass! | diff --git a/csharp/ql/test/library-tests/csharp8/PrintAst.expected b/csharp/ql/test/library-tests/csharp8/PrintAst.expected index d38d183151d..3a4cad07fc6 100644 --- a/csharp/ql/test/library-tests/csharp8/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp8/PrintAst.expected @@ -121,6 +121,42 @@ DefaultInterfaceMethods.cs: # 26| 7: [Method] Greet # 26| -1: [TypeMention] Void # 26| 4: [BlockStmt] {...} +NameResolutionSuppressNullable.cs: +# 5| [Class] MyClass2 +# 7| 5: [Field] s_signalMethod +# 7| -1: [TypeMention] WaitCallback +# 8| 6: [Property] SignalMethod +# 8| -1: [TypeMention] WaitCallback +# 8| 3: [Getter] get_SignalMethod +# 8| 4: [MethodCall] call to method EnsureInitialized +# 8| 0: [FieldAccess] access to field s_signalMethod +# 8| 1: [LambdaExpr] (...) => ... +# 8| 4: [ExplicitDelegateCreation] delegate creation of type WaitCallback +# 8| -1: [TypeMention] WaitCallback +# 8| 0: [SuppressNullableWarningExpr] ...! +# 8| 0: [MethodAccess] access to method M1 +# 10| 7: [Method] EnsureInitialized +# 10| -1: [TypeMention] T +#-----| 1: (Type parameters) +# 10| 0: [TypeParameter] T +#-----| 2: (Parameters) +# 10| 0: [Parameter] target +# 10| -1: [TypeMention] T +# 10| 1: [Parameter] valueFactory +# 10| -1: [TypeMention] Func +# 10| 1: [TypeMention] T +# 10| 4: [BlockStmt] {...} +# 10| 0: [ReturnStmt] return ...; +# 10| 0: [AssignExpr] ... = ... +# 10| 0: [ParameterAccess] access to parameter target +# 10| 1: [DelegateCall] delegate call +# 10| -1: [ParameterAccess] access to parameter valueFactory +# 12| 9: [Method] M1 +# 12| -1: [TypeMention] Void +#-----| 2: (Parameters) +# 12| 0: [Parameter] state +# 12| -1: [TypeMention] object +# 13| 4: [BlockStmt] {...} NullCoalescingAssignment.cs: # 3| [Class] NullCoalescingAssignment # 5| 5: [Method] NullCoalescing diff --git a/csharp/ql/test/library-tests/csharp9/CovariantReturn.cs b/csharp/ql/test/library-tests/csharp9/CovariantReturn.cs new file mode 100644 index 00000000000..ac39aae893d --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/CovariantReturn.cs @@ -0,0 +1,9 @@ +class A +{ + public virtual A M1() { throw null; } +} + +class B : A +{ + public override B M1() { throw null; } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected b/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected index d39e7d7d2af..2d2c60cecd8 100644 --- a/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected +++ b/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected @@ -5,6 +5,7 @@ type | file://:0:0:0:0 | delegate* default | readonly int | DefaultCallingConvention | | file://:0:0:0:0 | delegate* default | Void* | DefaultCallingConvention | | file://:0:0:0:0 | delegate* default | int | DefaultCallingConvention | +| file://:0:0:0:0 | delegate* default | Void | DefaultCallingConvention | | file://:0:0:0:0 | delegate* default | int | DefaultCallingConvention | | file://:0:0:0:0 | delegate* default | int* | DefaultCallingConvention | | file://:0:0:0:0 | delegate* stdcall | Void | StdCallCallingConvention | @@ -18,6 +19,9 @@ parameter | file://:0:0:0:0 | delegate* default | 0 | file://:0:0:0:0 | | ref int! | | file://:0:0:0:0 | delegate* default | 1 | file://:0:0:0:0 | `1 | out object? | | file://:0:0:0:0 | delegate* default | 0 | file://:0:0:0:0 | | int*! | +| file://:0:0:0:0 | delegate* default | 0 | file://:0:0:0:0 | | IntPtr! | +| file://:0:0:0:0 | delegate* default | 1 | file://:0:0:0:0 | `1 | IntPtr! | +| file://:0:0:0:0 | delegate* default | 2 | file://:0:0:0:0 | `2 | IntPtr*! | | file://:0:0:0:0 | delegate* default | 0 | file://:0:0:0:0 | | T | | file://:0:0:0:0 | delegate* default | 0 | file://:0:0:0:0 | | Void*! | | file://:0:0:0:0 | delegate* stdcall | 0 | file://:0:0:0:0 | | ref int! | diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected index 56299fbdc68..6da09ceb287 100644 --- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected @@ -117,6 +117,21 @@ BinaryPattern.cs: # 19| 1: [SwitchCaseExpr] ... => ... # 19| 0: [DiscardPatternExpr] _ # 19| 2: [StringLiteral] "other" +CovariantReturn.cs: +# 1| [Class] A +# 3| 5: [Method] M1 +# 3| -1: [TypeMention] A +# 3| 4: [BlockStmt] {...} +# 3| 0: [ThrowStmt] throw ...; +# 3| 0: [NullLiteral] null +# 6| [Class] B +#-----| 3: (Base types) +# 6| 0: [TypeMention] A +# 8| 5: [Method] M1 +# 8| -1: [TypeMention] B +# 8| 4: [BlockStmt] {...} +# 8| 0: [ThrowStmt] throw ...; +# 8| 0: [NullLiteral] null Discard.cs: # 3| [Class] Discard # 5| 5: [Method] M1 diff --git a/csharp/ql/test/library-tests/csharp9/covariantReturn.expected b/csharp/ql/test/library-tests/csharp9/covariantReturn.expected new file mode 100644 index 00000000000..789c8c7caaa --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/covariantReturn.expected @@ -0,0 +1 @@ +| A.M1 | A | B.M1 | B | diff --git a/csharp/ql/test/library-tests/csharp9/covariantReturn.ql b/csharp/ql/test/library-tests/csharp9/covariantReturn.ql new file mode 100644 index 00000000000..f4958cbba31 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/covariantReturn.ql @@ -0,0 +1,8 @@ +import csharp + +from Method m, Method overrider +where + m.getAnOverrider() = overrider and + m.getFile().getStem() = "CovariantReturn" +select m.getQualifiedName(), m.getReturnType().toString(), overrider.getQualifiedName(), + overrider.getReturnType().toString() diff --git a/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected b/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected index fe62037b779..8ea7f7d9875 100644 --- a/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected +++ b/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected @@ -257,8 +257,8 @@ | System.Collections.Concurrent.ConcurrentStack<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | | System.Collections.Concurrent.IProducerConsumerCollection<>.CopyTo(T[], int) | this parameter [[]] -> parameter 0 [[]] | true | | System.Collections.Concurrent.OrderablePartitioner<>.EnumerableDropIndices.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Collections.Concurrent.Partitioner.d__6.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Collections.Concurrent.Partitioner.d__9.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Collections.Concurrent.Partitioner.d__7.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Collections.Concurrent.Partitioner.d__10.GetEnumerator() | this parameter [[]] -> return [Current] | true | | System.Collections.Concurrent.Partitioner.DynamicPartitionerForArray<>.InternalPartitionEnumerable.GetEnumerator() | this parameter [[]] -> return [Current] | true | | System.Collections.Concurrent.Partitioner.DynamicPartitionerForIEnumerable<>.InternalPartitionEnumerable.GetEnumerator() | this parameter [[]] -> return [Current] | true | | System.Collections.Concurrent.Partitioner.DynamicPartitionerForIList<>.InternalPartitionEnumerable.GetEnumerator() | this parameter [[]] -> return [Current] | true | @@ -432,7 +432,7 @@ | System.Collections.Generic.SortedList<,>.set_Item(TKey, TValue) | parameter 1 -> this parameter [[], Value] | true | | System.Collections.Generic.SortedList<,>.set_Item(object, object) | parameter 0 -> this parameter [[], Key] | true | | System.Collections.Generic.SortedList<,>.set_Item(object, object) | parameter 1 -> this parameter [[], Value] | true | -| System.Collections.Generic.SortedSet<>.d__93.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Collections.Generic.SortedSet<>.d__84.GetEnumerator() | this parameter [[]] -> return [Current] | true | | System.Collections.Generic.SortedSet<>.Add(T) | parameter 0 -> this parameter [[]] | true | | System.Collections.Generic.SortedSet<>.CopyTo(Array, int) | this parameter [[]] -> parameter 0 [[]] | true | | System.Collections.Generic.SortedSet<>.CopyTo(T[], int) | this parameter [[]] -> parameter 0 [[]] | true | @@ -749,6 +749,8 @@ | System.Convert.ChangeType(object, TypeCode, IFormatProvider) | parameter 0 -> return | false | | System.Convert.FromBase64CharArray(Char[], int, int) | parameter 0 -> return | false | | System.Convert.FromBase64String(string) | parameter 0 -> return | false | +| System.Convert.FromHexString(ReadOnlySpan) | parameter 0 -> return | false | +| System.Convert.FromHexString(string) | parameter 0 -> return | false | | System.Convert.GetTypeCode(object) | parameter 0 -> return | false | | System.Convert.IsDBNull(object) | parameter 0 -> return | false | | System.Convert.ToBase64CharArray(Byte[], int, int, Char[], int) | parameter 0 -> return | false | @@ -867,6 +869,9 @@ | System.Convert.ToDouble(uint) | parameter 0 -> return | false | | System.Convert.ToDouble(ulong) | parameter 0 -> return | false | | System.Convert.ToDouble(ushort) | parameter 0 -> return | false | +| System.Convert.ToHexString(Byte[]) | parameter 0 -> return | false | +| System.Convert.ToHexString(Byte[], int, int) | parameter 0 -> return | false | +| System.Convert.ToHexString(ReadOnlySpan) | parameter 0 -> return | false | | System.Convert.ToInt16(DateTime) | parameter 0 -> return | false | | System.Convert.ToInt16(bool) | parameter 0 -> return | false | | System.Convert.ToInt16(byte) | parameter 0 -> return | false | @@ -1269,25 +1274,25 @@ | System.Lazy<>.Lazy(Func, bool) | deleget output from parameter 0 -> return [Value] | true | | System.Lazy<>.get_Value() | this parameter -> return | false | | System.Linq.EmptyPartition<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__63<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__80<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__97<,,,>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__100<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__104<,,,>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__61<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__173<,>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__176<,>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__178<,,>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__180<,,>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__193<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__189<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__191<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__220<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__216<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__218<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__239<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__242<,>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Linq.Enumerable.d__243<,,>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__64<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__81<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__98<,,,>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__101<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__105<,,,>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__62<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__174<,>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__177<,>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__179<,,>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__181<,,>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__194<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__190<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__192<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__221<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__217<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__219<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__240<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__243<,>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Linq.Enumerable.d__244<,,>.GetEnumerator() | this parameter [[]] -> return [Current] | true | | System.Linq.Enumerable.Aggregate(IEnumerable, TAccumulate, Func, Func) | deleget output from parameter 2 -> parameter 0 of delegate parameter 3 | true | | System.Linq.Enumerable.Aggregate(IEnumerable, TAccumulate, Func, Func) | deleget output from parameter 3 -> return | true | | System.Linq.Enumerable.Aggregate(IEnumerable, TAccumulate, Func, Func) | parameter 0 [[]] -> parameter 1 of delegate parameter 2 | true | @@ -1986,7 +1991,9 @@ | System.Net.Security.NegotiateStream.BeginRead(Byte[], int, int, AsyncCallback, object) | this parameter -> parameter 0 | false | | System.Net.Security.NegotiateStream.BeginWrite(Byte[], int, int, AsyncCallback, object) | parameter 0 -> this parameter | false | | System.Net.Security.NegotiateStream.Read(Byte[], int, int) | this parameter -> parameter 0 | false | +| System.Net.Security.NegotiateStream.ReadAsync(Byte[], int, int, CancellationToken) | this parameter -> parameter 0 | false | | System.Net.Security.NegotiateStream.Write(Byte[], int, int) | parameter 0 -> this parameter | false | +| System.Net.Security.NegotiateStream.WriteAsync(Byte[], int, int, CancellationToken) | parameter 0 -> this parameter | false | | System.Net.Security.SslStream.BeginRead(Byte[], int, int, AsyncCallback, object) | this parameter -> parameter 0 | false | | System.Net.Security.SslStream.BeginWrite(Byte[], int, int, AsyncCallback, object) | parameter 0 -> this parameter | false | | System.Net.Security.SslStream.Read(Byte[], int, int) | this parameter -> parameter 0 | false | @@ -2024,9 +2031,9 @@ | System.Runtime.CompilerServices.ReadOnlyCollectionBuilder<>.set_Item(int, T) | parameter 1 -> this parameter [[]] | true | | System.Runtime.CompilerServices.ReadOnlyCollectionBuilder<>.set_Item(int, object) | parameter 1 -> this parameter [[]] | true | | System.Runtime.CompilerServices.TaskAwaiter<>.GetResult() | this parameter [m_task, Result] -> return | true | -| System.Runtime.InteropServices.MemoryMarshal.d__3<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Runtime.Loader.AssemblyLoadContext.d__88.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Runtime.Loader.AssemblyLoadContext.d__58.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Runtime.InteropServices.MemoryMarshal.d__15<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Runtime.Loader.AssemblyLoadContext.d__83.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Runtime.Loader.AssemblyLoadContext.d__53.GetEnumerator() | this parameter [[]] -> return [Current] | true | | System.Runtime.Loader.LibraryNameVariation.d__5.GetEnumerator() | this parameter [[]] -> return [Current] | true | | System.Security.Cryptography.CryptoStream.BeginRead(Byte[], int, int, AsyncCallback, object) | this parameter -> parameter 0 | false | | System.Security.Cryptography.CryptoStream.BeginWrite(Byte[], int, int, AsyncCallback, object) | parameter 0 -> this parameter | false | @@ -2181,8 +2188,8 @@ | System.Text.RegularExpressions.CaptureCollection.get_Item(int) | this parameter [[]] -> return | true | | System.Text.RegularExpressions.CaptureCollection.set_Item(int, Capture) | parameter 1 -> this parameter [[]] | true | | System.Text.RegularExpressions.CaptureCollection.set_Item(int, object) | parameter 1 -> this parameter [[]] | true | -| System.Text.RegularExpressions.GroupCollection.d__48.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Text.RegularExpressions.GroupCollection.d__50.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Text.RegularExpressions.GroupCollection.d__49.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Text.RegularExpressions.GroupCollection.d__51.GetEnumerator() | this parameter [[]] -> return [Current] | true | | System.Text.RegularExpressions.GroupCollection.Add(Group) | parameter 0 -> this parameter [[]] | true | | System.Text.RegularExpressions.GroupCollection.Add(object) | parameter 0 -> this parameter [[]] | true | | System.Text.RegularExpressions.GroupCollection.CopyTo(Array, int) | this parameter [[]] -> parameter 0 [[]] | true | @@ -2257,6 +2264,12 @@ | System.Text.StringBuilder.StringBuilder(string, int, int, int) | parameter 0 -> return [[]] | true | | System.Text.StringBuilder.ToString() | this parameter [[]] -> return | false | | System.Text.StringBuilder.ToString(int, int) | this parameter [[]] -> return | false | +| System.Text.TranscodingStream.BeginRead(Byte[], int, int, AsyncCallback, object) | this parameter -> parameter 0 | false | +| System.Text.TranscodingStream.BeginWrite(Byte[], int, int, AsyncCallback, object) | parameter 0 -> this parameter | false | +| System.Text.TranscodingStream.Read(Byte[], int, int) | this parameter -> parameter 0 | false | +| System.Text.TranscodingStream.ReadAsync(Byte[], int, int, CancellationToken) | this parameter -> parameter 0 | false | +| System.Text.TranscodingStream.Write(Byte[], int, int) | parameter 0 -> this parameter | false | +| System.Text.TranscodingStream.WriteAsync(Byte[], int, int, CancellationToken) | parameter 0 -> this parameter | false | | System.Threading.Tasks.SingleProducerSingleConsumerQueue<>.GetEnumerator() | this parameter [[]] -> return [Current] | true | | System.Threading.Tasks.Task.ContinueWith(Action, object) | parameter 1 -> parameter 1 of delegate parameter 0 | true | | System.Threading.Tasks.Task.ContinueWith(Action, object, CancellationToken) | parameter 1 -> parameter 1 of delegate parameter 0 | true | @@ -2290,6 +2303,8 @@ | System.Threading.Tasks.Task.WhenAll(IEnumerable>) | parameter 0 [[], Result] -> return [Result, []] | true | | System.Threading.Tasks.Task.WhenAll(params Task[]) | parameter 0 [[], Result] -> return [Result, []] | true | | System.Threading.Tasks.Task.WhenAny(IEnumerable>) | parameter 0 [[], Result] -> return [Result, []] | true | +| System.Threading.Tasks.Task.WhenAny(Task, Task) | parameter 0 [[], Result] -> return [Result, []] | true | +| System.Threading.Tasks.Task.WhenAny(Task, Task) | parameter 1 [[], Result] -> return [Result, []] | true | | System.Threading.Tasks.Task.WhenAny(params Task[]) | parameter 0 [[], Result] -> return [Result, []] | true | | System.Threading.Tasks.Task<>.ConfigureAwait(bool) | this parameter -> return [m_configuredTaskAwaiter, m_task] | true | | System.Threading.Tasks.Task<>.ContinueWith(Action, Object>, object) | parameter 1 -> parameter 1 of delegate parameter 0 | true | @@ -2431,8 +2446,8 @@ | System.Threading.Tasks.TaskFactory<>.StartNew(Func, CancellationToken, TaskCreationOptions, TaskScheduler) | deleget output from parameter 0 -> return [Result] | true | | System.Threading.Tasks.TaskFactory<>.StartNew(Func, TaskCreationOptions) | deleget output from parameter 0 -> return [Result] | true | | System.Threading.Tasks.ThreadPoolTaskScheduler.d__6.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Threading.ThreadPool.d__51.GetEnumerator() | this parameter [[]] -> return [Current] | true | -| System.Threading.ThreadPool.d__50.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Threading.ThreadPool.d__52.GetEnumerator() | this parameter [[]] -> return [Current] | true | +| System.Threading.ThreadPool.d__51.GetEnumerator() | this parameter [[]] -> return [Current] | true | | System.Tuple.Create(T1, T2, T3, T4, T5, T6, T7, T8) | parameter 0 -> return [Item1] | true | | System.Tuple.Create(T1, T2, T3, T4, T5, T6, T7, T8) | parameter 1 -> return [Item2] | true | | System.Tuple.Create(T1, T2, T3, T4, T5, T6, T7, T8) | parameter 2 -> return [Item3] | true | diff --git a/csharp/ql/test/library-tests/dataflow/ssa/BaseSsaConsistency.ql b/csharp/ql/test/library-tests/dataflow/ssa/BaseSsaConsistency.ql index f2c262fb185..86e13215b0c 100644 --- a/csharp/ql/test/library-tests/dataflow/ssa/BaseSsaConsistency.ql +++ b/csharp/ql/test/library-tests/dataflow/ssa/BaseSsaConsistency.ql @@ -1,9 +1,11 @@ import csharp import semmle.code.csharp.dataflow.internal.BaseSSA -from AssignableRead ar, AssignableDefinition def, LocalScopeVariable v +from AssignableRead ar, BaseSsa::Definition ssaDef, AssignableDefinition def, LocalScopeVariable v where - ar = BaseSsa::getARead(def, v) and + ar = ssaDef.getARead() and + def = ssaDef.getDefinition() and + v = def.getTarget() and not exists(Ssa::ExplicitDefinition edef | edef.getADefinition() = def and edef.getARead() = ar diff --git a/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.ql b/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.ql index 9345525f486..849500904a0 100644 --- a/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.ql +++ b/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.ql @@ -1,5 +1,5 @@ import csharp -import semmle.code.csharp.controlflow.internal.PreSsa as PreSsa +import semmle.code.csharp.controlflow.internal.PreSsa import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl import semmle.code.csharp.dataflow.internal.SsaImpl as SsaImpl @@ -7,16 +7,14 @@ class CallableWithSplitting extends Callable { CallableWithSplitting() { this = any(SplitControlFlowElement e).getEnclosingCallable() } } -query predicate defReadInconsistency( - AssignableRead ar, Expr e, PreSsa::SimpleAssignable a, boolean b -) { +query predicate defReadInconsistency(AssignableRead ar, Expr e, PreSsa::SourceVariable v, boolean b) { // Exclude definitions in callables with CFG splitting, as SSA definitions may be // very different from pre-SSA definitions not ar.getEnclosingCallable() instanceof CallableWithSplitting and exists(AssignableDefinition def | e = def.getExpr() | b = true and - exists(PreSsa::Definition ssaDef | ssaDef.getAssignable() = a | - PreSsa::firstReadSameVar(ssaDef, ar) and + exists(PreSsa::Definition ssaDef | ssaDef.getSourceVariable() = v | + ar = ssaDef.getAFirstRead() and ssaDef.getDefinition() = def and not exists(Ssa::ExplicitDefinition edef | edef.getADefinition() = def and @@ -28,9 +26,9 @@ query predicate defReadInconsistency( exists(Ssa::ExplicitDefinition edef | edef.getADefinition() = def and edef.getAFirstRead() = ar and - def.getTarget() = a and + def.getTarget() = v and not exists(PreSsa::Definition ssaDef | - PreSsa::firstReadSameVar(ssaDef, ar) and + ar = ssaDef.getAFirstRead() and ssaDef.getDefinition() = def ) ) @@ -38,21 +36,21 @@ query predicate defReadInconsistency( } query predicate readReadInconsistency( - LocalScopeVariableRead read1, LocalScopeVariableRead read2, PreSsa::SimpleAssignable a, boolean b + LocalScopeVariableRead read1, LocalScopeVariableRead read2, PreSsa::SourceVariable v, boolean b ) { // Exclude definitions in callables with CFG splitting, as SSA definitions may be // very different from pre-SSA definitions not read1.getEnclosingCallable() instanceof CallableWithSplitting and ( b = true and - a = read1.getTarget() and + v = read1.getTarget() and PreSsa::adjacentReadPairSameVar(read1, read2) and not SsaImpl::adjacentReadPairSameVar(_, read1.getAControlFlowNode(), read2.getAControlFlowNode()) or b = false and - a = read1.getTarget() and + v = read1.getTarget() and SsaImpl::adjacentReadPairSameVar(_, read1.getAControlFlowNode(), read2.getAControlFlowNode()) and - read1.getTarget() instanceof PreSsa::SimpleAssignable and + read1.getTarget() instanceof PreSsa::SourceVariable and not PreSsa::adjacentReadPairSameVar(read1, read2) and // Exclude split CFG elements because SSA may be more precise than pre-SSA // in those cases @@ -61,17 +59,15 @@ query predicate readReadInconsistency( ) } -query predicate phiInconsistency( - ControlFlowElement cfe, Expr e, PreSsa::SimpleAssignable a, boolean b -) { +query predicate phiInconsistency(ControlFlowElement cfe, Expr e, PreSsa::SourceVariable v, boolean b) { // Exclude definitions in callables with CFG splitting, as SSA definitions may be // very different from pre-SSA definitions not cfe.getEnclosingCallable() instanceof CallableWithSplitting and exists(AssignableDefinition adef | e = adef.getExpr() | b = true and - exists(PreSsa::Definition def | a = def.getAssignable() | - adef = def.getAPhiInput+().getDefinition() and - cfe = def.getBasicBlock().getFirstElement() and + exists(PreSsa::PhiNode prePhi | v = prePhi.getSourceVariable() | + adef = prePhi.getAnInput+().getDefinition() and + cfe = prePhi.getBasicBlock().getFirstElement() and not exists(Ssa::PhiNode phi, ControlFlow::BasicBlock bb, Ssa::ExplicitDefinition edef | edef = phi.getAnUltimateDefinition() | @@ -83,15 +79,15 @@ query predicate phiInconsistency( or b = false and exists(Ssa::PhiNode phi, ControlFlow::BasicBlock bb, Ssa::ExplicitDefinition edef | - a = phi.getSourceVariable().getAssignable() + v = phi.getSourceVariable().getAssignable() | edef = phi.getAnUltimateDefinition() and edef.getADefinition() = adef and phi.definesAt(_, bb, _) and cfe = bb.getFirstNode().getElement() and - not exists(PreSsa::Definition def | - adef = def.getAPhiInput+().getDefinition() and - cfe = def.getBasicBlock().getFirstElement() + not exists(PreSsa::PhiNode prePhi | + adef = prePhi.getAnInput+().getDefinition() and + cfe = prePhi.getBasicBlock().getFirstElement() ) ) ) diff --git a/csharp/ql/test/query-tests/Stubs/MinimalStubsFromSource.expected b/csharp/ql/test/query-tests/Stubs/MinimalStubsFromSource.expected index 2bc65fe4614..d2dd3037e3c 100644 --- a/csharp/ql/test/query-tests/Stubs/MinimalStubsFromSource.expected +++ b/csharp/ql/test/query-tests/Stubs/MinimalStubsFromSource.expected @@ -1 +1 @@ -| // This file contains auto-generated code.\n// original-extractor-options: /r:System.Text.RegularExpressions.dll /r:System.Collections.Specialized.dll /r:System.Net.dll /r:System.Web.dll /r:System.Net.HttpListener.dll /r:System.Collections.Specialized.dll /r:System.Private.Uri.dll /r:System.Runtime.Extensions.dll /r:System.Linq.Parallel.dll /r:System.Collections.Concurrent.dll /r:System.Linq.Expressions.dll /r:System.Collections.dll /r:System.Linq.Queryable.dll /r:System.Linq.dll /r:System.Collections.NonGeneric.dll /r:System.ObjectModel.dll /r:System.ComponentModel.TypeConverter.dll /r:System.IO.Compression.dll /r:System.IO.Pipes.dll /r:System.Net.Primitives.dll /r:System.Net.Security.dll /r:System.Security.Cryptography.Primitives.dll /r:System.Text.RegularExpressions.dll ${testdir}/../../resources/stubs/System.Web.cs /r:System.Runtime.Serialization.Primitives.dll\n\nnamespace System\n{\n// Generated from `System.Uri` in `System.Private.Uri, Version=4.0.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Uri : System.Runtime.Serialization.ISerializable\n{\n public override bool Equals(object comparand) => throw null;\n public override int GetHashCode() => throw null;\n public override string ToString() => throw null;\n void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) => throw null;\n}\n\nnamespace Collections\n{\n// Generated from `System.Collections.Queue` in `System.Collections.NonGeneric, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Queue : System.ICloneable, System.Collections.IEnumerable, System.Collections.ICollection\n{\n public virtual System.Collections.IEnumerator GetEnumerator() => throw null;\n public virtual bool IsSynchronized { get => throw null; }\n public virtual int Count { get => throw null; }\n public virtual object Clone() => throw null;\n public virtual object SyncRoot { get => throw null; }\n public virtual void CopyTo(System.Array array, int index) => throw null;\n}\n\n// Generated from `System.Collections.SortedList` in `System.Collections.NonGeneric, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class SortedList : System.ICloneable, System.Collections.IEnumerable, System.Collections.IDictionary, System.Collections.ICollection\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public virtual System.Collections.ICollection Keys { get => throw null; }\n public virtual System.Collections.ICollection Values { get => throw null; }\n public virtual System.Collections.IDictionaryEnumerator GetEnumerator() => throw null;\n public virtual bool Contains(object key) => throw null;\n public virtual bool IsFixedSize { get => throw null; }\n public virtual bool IsReadOnly { get => throw null; }\n public virtual bool IsSynchronized { get => throw null; }\n public virtual int Count { get => throw null; }\n public virtual object Clone() => throw null;\n public virtual object GetByIndex(int index) => throw null;\n public virtual object SyncRoot { get => throw null; }\n public virtual object this[object key] { get => throw null; set => throw null; }\n public virtual void Add(object key, object value) => throw null;\n public virtual void Clear() => throw null;\n public virtual void CopyTo(System.Array array, int arrayIndex) => throw null;\n public virtual void Remove(object key) => throw null;\n}\n\n// Generated from `System.Collections.Stack` in `System.Collections.NonGeneric, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Stack : System.ICloneable, System.Collections.IEnumerable, System.Collections.ICollection\n{\n public virtual System.Collections.IEnumerator GetEnumerator() => throw null;\n public virtual bool IsSynchronized { get => throw null; }\n public virtual int Count { get => throw null; }\n public virtual object Clone() => throw null;\n public virtual object SyncRoot { get => throw null; }\n public virtual void CopyTo(System.Array array, int index) => throw null;\n}\n\nnamespace Concurrent\n{\n// Generated from `System.Collections.Concurrent.BlockingCollection<>` in `System.Collections.Concurrent, Version=4.0.15.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class BlockingCollection : System.IDisposable, System.Collections.IEnumerable, System.Collections.ICollection, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IEnumerable\n{\n System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null;\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n public int Count { get => throw null; }\n public void Dispose() => throw null;\n void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null;\n}\n\n// Generated from `System.Collections.Concurrent.BlockingCollectionDebugView<>` in `System.Collections.Concurrent, Version=4.0.15.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass BlockingCollectionDebugView\n{\n}\n\n// Generated from `System.Collections.Concurrent.ConcurrentDictionary<,>` in `System.Collections.Concurrent, Version=4.0.15.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ConcurrentDictionary : System.Collections.IEnumerable, System.Collections.IDictionary, System.Collections.ICollection, System.Collections.Generic.IReadOnlyDictionary, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IDictionary, System.Collections.Generic.ICollection>\n{\n System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Keys { get => throw null; }\n System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Values { get => throw null; }\n System.Collections.ICollection System.Collections.IDictionary.Keys { get => throw null; }\n System.Collections.ICollection System.Collections.IDictionary.Values { get => throw null; }\n System.Collections.IDictionaryEnumerator System.Collections.IDictionary.GetEnumerator() => throw null;\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n bool System.Collections.Generic.ICollection>.Contains(System.Collections.Generic.KeyValuePair keyValuePair) => throw null;\n bool System.Collections.Generic.ICollection>.IsReadOnly { get => throw null; }\n bool System.Collections.Generic.ICollection>.Remove(System.Collections.Generic.KeyValuePair keyValuePair) => throw null;\n bool System.Collections.Generic.IDictionary.Remove(TKey key) => throw null;\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n bool System.Collections.IDictionary.Contains(object key) => throw null;\n bool System.Collections.IDictionary.IsFixedSize { get => throw null; }\n bool System.Collections.IDictionary.IsReadOnly { get => throw null; }\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n object this[object key] { get => throw null; set => throw null; }\n public System.Collections.Generic.ICollection Keys { get => throw null; }\n public System.Collections.Generic.ICollection Values { get => throw null; }\n public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null;\n public TValue this[TKey key] { get => throw null; set => throw null; }\n public bool ContainsKey(TKey key) => throw null;\n public bool TryGetValue(TKey key, out TValue value) => throw null;\n public int Count { get => throw null; }\n public void Clear() => throw null;\n void System.Collections.Generic.ICollection>.Add(System.Collections.Generic.KeyValuePair keyValuePair) => throw null;\n void System.Collections.Generic.ICollection>.CopyTo(System.Collections.Generic.KeyValuePair[] array, int index) => throw null;\n void System.Collections.Generic.IDictionary.Add(TKey key, TValue value) => throw null;\n void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null;\n void System.Collections.IDictionary.Add(object key, object value) => throw null;\n void System.Collections.IDictionary.Remove(object key) => throw null;\n}\n\n// Generated from `System.Collections.Concurrent.IDictionaryDebugView<,>` in `System.Collections.Concurrent, Version=4.0.15.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass IDictionaryDebugView\n{\n}\n\n}\nnamespace Generic\n{\n// Generated from `System.Collections.Generic.CollectionDebugView<>` in `System.ObjectModel, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass CollectionDebugView\n{\n}\n\n// Generated from `System.Collections.Generic.DictionaryDebugView<,>` in `System.ObjectModel, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass DictionaryDebugView\n{\n}\n\n// Generated from `System.Collections.Generic.QueueDebugView<>` in `System.Collections, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass QueueDebugView\n{\n}\n\n// Generated from `System.Collections.Generic.SortedSet<>` in `System.Collections, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class SortedSet : System.Runtime.Serialization.ISerializable, System.Runtime.Serialization.IDeserializationCallback, System.Collections.IEnumerable, System.Collections.ICollection, System.Collections.Generic.ISet, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.ICollection\n{\n System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null;\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n bool System.Collections.Generic.ICollection.IsReadOnly { get => throw null; }\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n public bool Add(T item) => throw null;\n public bool IsProperSubsetOf(System.Collections.Generic.IEnumerable other) => throw null;\n public bool IsProperSupersetOf(System.Collections.Generic.IEnumerable other) => throw null;\n public bool IsSubsetOf(System.Collections.Generic.IEnumerable other) => throw null;\n public bool IsSupersetOf(System.Collections.Generic.IEnumerable other) => throw null;\n public bool Overlaps(System.Collections.Generic.IEnumerable other) => throw null;\n public bool Remove(T item) => throw null;\n public bool SetEquals(System.Collections.Generic.IEnumerable other) => throw null;\n public int Count { get => throw null; }\n public virtual bool Contains(T item) => throw null;\n public virtual void Clear() => throw null;\n public virtual void IntersectWith(System.Collections.Generic.IEnumerable other) => throw null;\n public void CopyTo(T[] array, int index) => throw null;\n public void ExceptWith(System.Collections.Generic.IEnumerable other) => throw null;\n public void SymmetricExceptWith(System.Collections.Generic.IEnumerable other) => throw null;\n public void UnionWith(System.Collections.Generic.IEnumerable other) => throw null;\n void System.Collections.Generic.ICollection.Add(T item) => throw null;\n void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null;\n void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) => throw null;\n void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null;\n}\n\n// Generated from `System.Collections.Generic.Stack<>` in `System.Collections, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Stack : System.Collections.IEnumerable, System.Collections.ICollection, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IEnumerable\n{\n System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null;\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n public T Peek() => throw null;\n public int Count { get => throw null; }\n void System.Collections.ICollection.CopyTo(System.Array array, int arrayIndex) => throw null;\n}\n\n// Generated from `System.Collections.Generic.StackDebugView<>` in `System.Collections, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass StackDebugView\n{\n}\n\n}\nnamespace Specialized\n{\n// Generated from `System.Collections.Specialized.NameObjectCollectionBase` in `System.Collections.Specialized, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract public class NameObjectCollectionBase : System.Runtime.Serialization.ISerializable, System.Runtime.Serialization.IDeserializationCallback, System.Collections.IEnumerable, System.Collections.ICollection\n{\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n public virtual System.Collections.IEnumerator GetEnumerator() => throw null;\n public virtual int Count { get => throw null; }\n public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null;\n public virtual void OnDeserialization(object sender) => throw null;\n void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null;\n}\n\n// Generated from `System.Collections.Specialized.NameValueCollection` in `System.Collections.Specialized, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class NameValueCollection : System.Collections.Specialized.NameObjectCollectionBase\n{\n public string this[string name] { get => throw null; set => throw null; }\n}\n\n}\n}\nnamespace ComponentModel\n{\n// Generated from `System.ComponentModel.ComponentConverter` in `System.ComponentModel.TypeConverter, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ComponentConverter : System.ComponentModel.ReferenceConverter\n{\n}\n\n// Generated from `System.ComponentModel.DefaultEventAttribute` in `System.ComponentModel.TypeConverter, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DefaultEventAttribute : System.Attribute\n{\n public DefaultEventAttribute(string name) => throw null;\n public override bool Equals(object obj) => throw null;\n public override int GetHashCode() => throw null;\n}\n\n// Generated from `System.ComponentModel.DefaultPropertyAttribute` in `System.ComponentModel.TypeConverter, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DefaultPropertyAttribute : System.Attribute\n{\n public DefaultPropertyAttribute(string name) => throw null;\n public override bool Equals(object obj) => throw null;\n public override int GetHashCode() => throw null;\n}\n\n// Generated from `System.ComponentModel.DesignerAttribute` in `System.ComponentModel.TypeConverter, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DesignerAttribute : System.Attribute\n{\n public DesignerAttribute(System.Type designerType) => throw null;\n public DesignerAttribute(System.Type designerType, System.Type designerBaseType) => throw null;\n public DesignerAttribute(string designerTypeName) => throw null;\n public DesignerAttribute(string designerTypeName, System.Type designerBaseType) => throw null;\n public DesignerAttribute(string designerTypeName, string designerBaseTypeName) => throw null;\n public override bool Equals(object obj) => throw null;\n public override int GetHashCode() => throw null;\n public override object TypeId { get => throw null; }\n}\n\n// Generated from `System.ComponentModel.INotifyPropertyChanged` in `System.ObjectModel, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface INotifyPropertyChanged\n{\n}\n\n// Generated from `System.ComponentModel.ReferenceConverter` in `System.ComponentModel.TypeConverter, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ReferenceConverter : System.ComponentModel.TypeConverter\n{\n}\n\n// Generated from `System.ComponentModel.TypeConverterAttribute` in `System.ObjectModel, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TypeConverterAttribute : System.Attribute\n{\n public TypeConverterAttribute() => throw null;\n public TypeConverterAttribute(System.Type type) => throw null;\n public TypeConverterAttribute(string typeName) => throw null;\n public override bool Equals(object obj) => throw null;\n public override int GetHashCode() => throw null;\n}\n\n// Generated from `System.ComponentModel.TypeConverter` in `System.ComponentModel.TypeConverter, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TypeConverter\n{\n}\n\n// Generated from `System.ComponentModel.TypeDescriptionProviderAttribute` in `System.ObjectModel, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TypeDescriptionProviderAttribute : System.Attribute\n{\n public TypeDescriptionProviderAttribute(System.Type type) => throw null;\n public TypeDescriptionProviderAttribute(string typeName) => throw null;\n}\n\n// Generated from `System.ComponentModel.TypeDescriptionProvider` in `System.ComponentModel.TypeConverter, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract public class TypeDescriptionProvider\n{\n}\n\n// Generated from `System.ComponentModel.TypeDescriptor` in `System.ComponentModel.TypeConverter, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TypeDescriptor\n{\n}\n\nnamespace Design\n{\n// Generated from `System.ComponentModel.Design.DesignerOptionService` in `System.ComponentModel.TypeConverter, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract public class DesignerOptionService : System.ComponentModel.Design.IDesignerOptionService\n{\n}\n\n// Generated from `System.ComponentModel.Design.IDesignerOptionService` in `System.ComponentModel.TypeConverter, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface IDesignerOptionService\n{\n}\n\n// Generated from `System.ComponentModel.Design.IDesigner` in `System.ComponentModel.TypeConverter, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface IDesigner : System.IDisposable\n{\n}\n\n// Generated from `System.ComponentModel.Design.IRootDesigner` in `System.ComponentModel.TypeConverter, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface IRootDesigner : System.IDisposable, System.ComponentModel.Design.IDesigner\n{\n}\n\n}\n}\nnamespace Dynamic\n{\n// Generated from `System.Dynamic.BindingRestrictions` in `System.Linq.Expressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract public class BindingRestrictions\n{\n}\n\n// Generated from `System.Dynamic.DynamicMetaObject` in `System.Linq.Expressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DynamicMetaObject\n{\n}\n\n// Generated from `System.Dynamic.ExpandoObject` in `System.Linq.Expressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ExpandoObject : System.Dynamic.IDynamicMetaObjectProvider, System.ComponentModel.INotifyPropertyChanged, System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IDictionary, System.Collections.Generic.ICollection>\n{\n System.Collections.Generic.ICollection System.Collections.Generic.IDictionary.Values { get => throw null; }\n System.Collections.Generic.ICollection System.Collections.Generic.IDictionary.Keys { get => throw null; }\n System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() => throw null;\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n bool System.Collections.Generic.ICollection>.Contains(System.Collections.Generic.KeyValuePair item) => throw null;\n bool System.Collections.Generic.ICollection>.IsReadOnly { get => throw null; }\n bool System.Collections.Generic.ICollection>.Remove(System.Collections.Generic.KeyValuePair item) => throw null;\n bool System.Collections.Generic.IDictionary.ContainsKey(string key) => throw null;\n bool System.Collections.Generic.IDictionary.Remove(string key) => throw null;\n bool System.Collections.Generic.IDictionary.TryGetValue(string key, out object value) => throw null;\n int System.Collections.Generic.ICollection>.Count { get => throw null; }\n object this[string key] { get => throw null; set => throw null; }\n void System.Collections.Generic.ICollection>.Add(System.Collections.Generic.KeyValuePair item) => throw null;\n void System.Collections.Generic.ICollection>.Clear() => throw null;\n void System.Collections.Generic.ICollection>.CopyTo(System.Collections.Generic.KeyValuePair[] array, int arrayIndex) => throw null;\n void System.Collections.Generic.IDictionary.Add(string key, object value) => throw null;\n}\n\n// Generated from `System.Dynamic.IDynamicMetaObjectProvider` in `System.Linq.Expressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface IDynamicMetaObjectProvider\n{\n}\n\nnamespace Utils\n{\n// Generated from `System.Dynamic.Utils.ListProvider<>` in `System.Linq.Expressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract class ListProvider : System.Collections.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IEnumerable, System.Collections.Generic.ICollection where T: class\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public System.Collections.Generic.IEnumerator GetEnumerator() => throw null;\n public T this[int index] { get => throw null; set => throw null; }\n public bool Contains(T item) => throw null;\n public bool IsReadOnly { get => throw null; }\n public bool Remove(T item) => throw null;\n public int Count { get => throw null; }\n public int IndexOf(T item) => throw null;\n public void Add(T item) => throw null;\n public void Clear() => throw null;\n public void CopyTo(T[] array, int index) => throw null;\n public void Insert(int index, T item) => throw null;\n public void RemoveAt(int index) => throw null;\n}\n\n}\n}\nnamespace IO\n{\n// Generated from `System.IO.BufferedStream` in `System.Runtime.Extensions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class BufferedStream : System.IO.Stream\n{\n protected override void Dispose(bool disposing) => throw null;\n public override System.IAsyncResult BeginRead(System.Byte[] buffer, int offset, int count, System.AsyncCallback callback, object state) => throw null;\n public override System.IAsyncResult BeginWrite(System.Byte[] buffer, int offset, int count, System.AsyncCallback callback, object state) => throw null;\n public override System.Int64 Length { get => throw null; }\n public override System.Int64 Position { get => throw null; set => throw null; }\n public override System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin) => throw null;\n public override System.Threading.Tasks.Task CopyToAsync(System.IO.Stream destination, int bufferSize, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.Task WriteAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.Task ReadAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.ValueTask DisposeAsync() => throw null;\n public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.ValueTask ReadAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken) => throw null;\n public override bool CanRead { get => throw null; }\n public override bool CanSeek { get => throw null; }\n public override bool CanWrite { get => throw null; }\n public override int EndRead(System.IAsyncResult asyncResult) => throw null;\n public override int Read(System.Byte[] array, int offset, int count) => throw null;\n public override int Read(System.Span destination) => throw null;\n public override int ReadByte() => throw null;\n public override void CopyTo(System.IO.Stream destination, int bufferSize) => throw null;\n public override void EndWrite(System.IAsyncResult asyncResult) => throw null;\n public override void Flush() => throw null;\n public override void SetLength(System.Int64 value) => throw null;\n public override void Write(System.Byte[] array, int offset, int count) => throw null;\n public override void Write(System.ReadOnlySpan buffer) => throw null;\n public override void WriteByte(System.Byte value) => throw null;\n}\n\n// Generated from `System.IO.StringReader` in `System.Runtime.Extensions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class StringReader : System.IO.TextReader\n{\n protected override void Dispose(bool disposing) => throw null;\n public StringReader(string s) => throw null;\n public override System.Threading.Tasks.Task ReadAsync(System.Char[] buffer, int index, int count) => throw null;\n public override System.Threading.Tasks.Task ReadBlockAsync(System.Char[] buffer, int index, int count) => throw null;\n public override System.Threading.Tasks.Task ReadLineAsync() => throw null;\n public override System.Threading.Tasks.Task ReadToEndAsync() => throw null;\n public override System.Threading.Tasks.ValueTask ReadAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.ValueTask ReadBlockAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken) => throw null;\n public override int Peek() => throw null;\n public override int Read() => throw null;\n public override int Read(System.Char[] buffer, int index, int count) => throw null;\n public override int Read(System.Span buffer) => throw null;\n public override int ReadBlock(System.Span buffer) => throw null;\n public override string ReadLine() => throw null;\n public override string ReadToEnd() => throw null;\n public override void Close() => throw null;\n}\n\nnamespace Compression\n{\n// Generated from `System.IO.Compression.DeflateStream` in `System.IO.Compression, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089`\npublic class DeflateStream : System.IO.Stream\n{\n protected override void Dispose(bool disposing) => throw null;\n public override System.IAsyncResult BeginRead(System.Byte[] buffer, int offset, int count, System.AsyncCallback asyncCallback, object asyncState) => throw null;\n public override System.IAsyncResult BeginWrite(System.Byte[] array, int offset, int count, System.AsyncCallback asyncCallback, object asyncState) => throw null;\n public override System.Int64 Length { get => throw null; }\n public override System.Int64 Position { get => throw null; set => throw null; }\n public override System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin) => throw null;\n public override System.Threading.Tasks.Task CopyToAsync(System.IO.Stream destination, int bufferSize, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.Task WriteAsync(System.Byte[] array, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.Task ReadAsync(System.Byte[] array, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.ValueTask DisposeAsync() => throw null;\n public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.ValueTask ReadAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken) => throw null;\n public override bool CanRead { get => throw null; }\n public override bool CanSeek { get => throw null; }\n public override bool CanWrite { get => throw null; }\n public override int EndRead(System.IAsyncResult asyncResult) => throw null;\n public override int Read(System.Byte[] array, int offset, int count) => throw null;\n public override int Read(System.Span buffer) => throw null;\n public override int ReadByte() => throw null;\n public override void CopyTo(System.IO.Stream destination, int bufferSize) => throw null;\n public override void EndWrite(System.IAsyncResult asyncResult) => throw null;\n public override void Flush() => throw null;\n public override void SetLength(System.Int64 value) => throw null;\n public override void Write(System.Byte[] array, int offset, int count) => throw null;\n public override void Write(System.ReadOnlySpan buffer) => throw null;\n}\n\n}\n}\nnamespace Linq\n{\n// Generated from `System.Linq.Enumerable` in `System.Linq, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nstatic public class Enumerable\n{\n public static System.Collections.Generic.IEnumerable Select(this System.Collections.Generic.IEnumerable source, System.Func selector) => throw null;\n}\n\n// Generated from `System.Linq.Grouping<,>` in `System.Linq, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Grouping : System.Linq.IGrouping, System.Collections.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IEnumerable, System.Collections.Generic.ICollection\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n TElement this[int index] { get => throw null; set => throw null; }\n bool System.Collections.Generic.ICollection.Contains(TElement item) => throw null;\n bool System.Collections.Generic.ICollection.IsReadOnly { get => throw null; }\n bool System.Collections.Generic.ICollection.Remove(TElement item) => throw null;\n int System.Collections.Generic.ICollection.Count { get => throw null; }\n int System.Collections.Generic.IList.IndexOf(TElement item) => throw null;\n public System.Collections.Generic.IEnumerator GetEnumerator() => throw null;\n void System.Collections.Generic.ICollection.Add(TElement item) => throw null;\n void System.Collections.Generic.ICollection.Clear() => throw null;\n void System.Collections.Generic.ICollection.CopyTo(TElement[] array, int arrayIndex) => throw null;\n void System.Collections.Generic.IList.Insert(int index, TElement item) => throw null;\n void System.Collections.Generic.IList.RemoveAt(int index) => throw null;\n}\n\n// Generated from `System.Linq.IGrouping<,>` in `System.Linq, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface IGrouping : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable\n{\n}\n\n// Generated from `System.Linq.IIListProvider<>` in `System.Linq, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\ninterface IIListProvider : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable\n{\n}\n\n// Generated from `System.Linq.ILookup<,>` in `System.Linq, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface ILookup : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>\n{\n}\n\n// Generated from `System.Linq.IOrderedEnumerable<>` in `System.Linq, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface IOrderedEnumerable : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable\n{\n}\n\n// Generated from `System.Linq.IPartition<>` in `System.Linq, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\ninterface IPartition : System.Linq.IIListProvider, System.Collections.IEnumerable, System.Collections.Generic.IEnumerable\n{\n}\n\n// Generated from `System.Linq.IQueryable` in `System.Linq.Expressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface IQueryable : System.Collections.IEnumerable\n{\n}\n\n// Generated from `System.Linq.Lookup<,>` in `System.Linq, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Lookup : System.Linq.ILookup, System.Linq.IIListProvider>, System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null;\n}\n\n// Generated from `System.Linq.OrderedEnumerable<>` in `System.Linq, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract class OrderedEnumerable : System.Linq.IPartition, System.Linq.IOrderedEnumerable, System.Linq.IIListProvider, System.Collections.IEnumerable, System.Collections.Generic.IEnumerable\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public System.Collections.Generic.IEnumerator GetEnumerator() => throw null;\n}\n\n// Generated from `System.Linq.ParallelEnumerable` in `System.Linq.Parallel, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nstatic public class ParallelEnumerable\n{\n public static System.Linq.ParallelQuery AsParallel(this System.Collections.IEnumerable source) => throw null;\n}\n\n// Generated from `System.Linq.ParallelQuery<>` in `System.Linq.Parallel, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ParallelQuery : System.Linq.ParallelQuery, System.Collections.IEnumerable, System.Collections.Generic.IEnumerable\n{\n public virtual System.Collections.Generic.IEnumerator GetEnumerator() => throw null;\n}\n\n// Generated from `System.Linq.ParallelQuery` in `System.Linq.Parallel, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ParallelQuery : System.Collections.IEnumerable\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n}\n\n// Generated from `System.Linq.Queryable` in `System.Linq.Queryable, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nstatic public class Queryable\n{\n public static System.Linq.IQueryable AsQueryable(this System.Collections.IEnumerable source) => throw null;\n}\n\n// Generated from `System.Linq.SystemLinq_GroupingDebugView<,>` in `System.Linq, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass SystemLinq_GroupingDebugView\n{\n}\n\n// Generated from `System.Linq.SystemLinq_LookupDebugView<,>` in `System.Linq, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass SystemLinq_LookupDebugView\n{\n}\n\nnamespace Expressions\n{\n// Generated from `System.Linq.Expressions.BlockExpressionList` in `System.Linq.Expressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass BlockExpressionList : System.Collections.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IEnumerable, System.Collections.Generic.ICollection\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public System.Collections.Generic.IEnumerator GetEnumerator() => throw null;\n public System.Linq.Expressions.Expression this[int index] { get => throw null; set => throw null; }\n public bool Contains(System.Linq.Expressions.Expression item) => throw null;\n public bool IsReadOnly { get => throw null; }\n public bool Remove(System.Linq.Expressions.Expression item) => throw null;\n public int Count { get => throw null; }\n public int IndexOf(System.Linq.Expressions.Expression item) => throw null;\n public void Add(System.Linq.Expressions.Expression item) => throw null;\n public void Clear() => throw null;\n public void CopyTo(System.Linq.Expressions.Expression[] array, int index) => throw null;\n public void Insert(int index, System.Linq.Expressions.Expression item) => throw null;\n public void RemoveAt(int index) => throw null;\n}\n\n// Generated from `System.Linq.Expressions.Expression` in `System.Linq.Expressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract public class Expression\n{\n public override string ToString() => throw null;\n}\n\n// Generated from `System.Linq.Expressions.ParameterExpression` in `System.Linq.Expressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ParameterExpression : System.Linq.Expressions.Expression\n{\n}\n\nnamespace Compiler\n{\n// Generated from `System.Linq.Expressions.Compiler.ParameterList` in `System.Linq.Expressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass ParameterList : System.Collections.IEnumerable, System.Collections.Generic.IReadOnlyList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IEnumerable\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public System.Collections.Generic.IEnumerator GetEnumerator() => throw null;\n public System.Linq.Expressions.ParameterExpression this[int index] { get => throw null; }\n public int Count { get => throw null; }\n}\n\n}\nnamespace Interpreter\n{\n// Generated from `System.Linq.Expressions.Interpreter.InstructionArray` in `System.Linq.Expressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nstruct InstructionArray\n{\n}\n\n// Generated from `System.Linq.Expressions.Interpreter.InstructionList` in `System.Linq.Expressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass InstructionList\n{\n}\n\n// Generated from `System.Linq.Expressions.Interpreter.InterpretedFrameInfo` in `System.Linq.Expressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nstruct InterpretedFrameInfo\n{\n public override string ToString() => throw null;\n}\n\n// Generated from `System.Linq.Expressions.Interpreter.InterpretedFrame` in `System.Linq.Expressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass InterpretedFrame\n{\n}\n\n}\n}\nnamespace Parallel\n{\n// Generated from `System.Linq.Parallel.ListChunk<>` in `System.Linq.Parallel, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass ListChunk : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public System.Collections.Generic.IEnumerator GetEnumerator() => throw null;\n}\n\n// Generated from `System.Linq.Parallel.Lookup<,>` in `System.Linq.Parallel, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass Lookup : System.Linq.ILookup, System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null;\n}\n\n// Generated from `System.Linq.Parallel.PartitionerQueryOperator<>` in `System.Linq.Parallel, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass PartitionerQueryOperator : System.Linq.Parallel.QueryOperator\n{\n}\n\n// Generated from `System.Linq.Parallel.QueryOperator<>` in `System.Linq.Parallel, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract class QueryOperator : System.Linq.ParallelQuery\n{\n public override System.Collections.Generic.IEnumerator GetEnumerator() => throw null;\n}\n\n// Generated from `System.Linq.Parallel.QueryResults<>` in `System.Linq.Parallel, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract class QueryResults : System.Collections.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IEnumerable, System.Collections.Generic.ICollection\n{\n System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null;\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n bool System.Collections.Generic.ICollection.Contains(T item) => throw null;\n bool System.Collections.Generic.ICollection.IsReadOnly { get => throw null; }\n bool System.Collections.Generic.ICollection.Remove(T item) => throw null;\n int System.Collections.Generic.IList.IndexOf(T item) => throw null;\n public T this[int index] { get => throw null; set => throw null; }\n public int Count { get => throw null; }\n void System.Collections.Generic.ICollection.Add(T item) => throw null;\n void System.Collections.Generic.ICollection.Clear() => throw null;\n void System.Collections.Generic.ICollection.CopyTo(T[] array, int arrayIndex) => throw null;\n void System.Collections.Generic.IList.Insert(int index, T item) => throw null;\n void System.Collections.Generic.IList.RemoveAt(int index) => throw null;\n}\n\n// Generated from `System.Linq.Parallel.ZipQueryOperator<,,>` in `System.Linq.Parallel, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass ZipQueryOperator : System.Linq.Parallel.QueryOperator\n{\n}\n\n}\n}\nnamespace Net\n{\n// Generated from `System.Net.CookieCollection` in `System.Net.Primitives, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class CookieCollection : System.Collections.IEnumerable, System.Collections.ICollection, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.ICollection\n{\n System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null;\n public System.Collections.IEnumerator GetEnumerator() => throw null;\n public bool Contains(System.Net.Cookie cookie) => throw null;\n public bool IsReadOnly { get => throw null; }\n public bool IsSynchronized { get => throw null; }\n public bool Remove(System.Net.Cookie cookie) => throw null;\n public int Count { get => throw null; }\n public object SyncRoot { get => throw null; }\n public void Add(System.Net.Cookie cookie) => throw null;\n public void Clear() => throw null;\n public void CopyTo(System.Array array, int index) => throw null;\n public void CopyTo(System.Net.Cookie[] array, int index) => throw null;\n}\n\n// Generated from `System.Net.Cookie` in `System.Net.Primitives, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Cookie\n{\n public override bool Equals(object comparand) => throw null;\n public override int GetHashCode() => throw null;\n public override string ToString() => throw null;\n}\n\n// Generated from `System.Net.FixedSizeReader` in `System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nstatic class FixedSizeReader\n{\n}\n\nnamespace Security\n{\n// Generated from `System.Net.Security.AuthenticatedStream` in `System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract public class AuthenticatedStream : System.IO.Stream\n{\n protected override void Dispose(bool disposing) => throw null;\n public override System.Threading.Tasks.ValueTask DisposeAsync() => throw null;\n}\n\n// Generated from `System.Net.Security.CipherSuitesPolicy` in `System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class CipherSuitesPolicy\n{\n}\n\n// Generated from `System.Net.Security.NegotiateStream` in `System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class NegotiateStream : System.Net.Security.AuthenticatedStream\n{\n protected override void Dispose(bool disposing) => throw null;\n public override System.IAsyncResult BeginRead(System.Byte[] buffer, int offset, int count, System.AsyncCallback asyncCallback, object asyncState) => throw null;\n public override System.IAsyncResult BeginWrite(System.Byte[] buffer, int offset, int count, System.AsyncCallback asyncCallback, object asyncState) => throw null;\n public override System.Int64 Length { get => throw null; }\n public override System.Int64 Position { get => throw null; set => throw null; }\n public override System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin) => throw null;\n public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.ValueTask DisposeAsync() => throw null;\n public override bool CanRead { get => throw null; }\n public override bool CanSeek { get => throw null; }\n public override bool CanTimeout { get => throw null; }\n public override bool CanWrite { get => throw null; }\n public override int EndRead(System.IAsyncResult asyncResult) => throw null;\n public override int Read(System.Byte[] buffer, int offset, int count) => throw null;\n public override int ReadTimeout { get => throw null; set => throw null; }\n public override int WriteTimeout { get => throw null; set => throw null; }\n public override void EndWrite(System.IAsyncResult asyncResult) => throw null;\n public override void Flush() => throw null;\n public override void SetLength(System.Int64 value) => throw null;\n public override void Write(System.Byte[] buffer, int offset, int count) => throw null;\n}\n\n// Generated from `System.Net.Security.SslStream` in `System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class SslStream : System.Net.Security.AuthenticatedStream\n{\n protected override void Dispose(bool disposing) => throw null;\n public override System.IAsyncResult BeginRead(System.Byte[] buffer, int offset, int count, System.AsyncCallback asyncCallback, object asyncState) => throw null;\n public override System.IAsyncResult BeginWrite(System.Byte[] buffer, int offset, int count, System.AsyncCallback asyncCallback, object asyncState) => throw null;\n public override System.Int64 Length { get => throw null; }\n public override System.Int64 Position { get => throw null; set => throw null; }\n public override System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin) => throw null;\n public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.Task WriteAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.Task ReadAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.ValueTask DisposeAsync() => throw null;\n public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.ValueTask ReadAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken) => throw null;\n public override bool CanRead { get => throw null; }\n public override bool CanSeek { get => throw null; }\n public override bool CanTimeout { get => throw null; }\n public override bool CanWrite { get => throw null; }\n public override int EndRead(System.IAsyncResult asyncResult) => throw null;\n public override int Read(System.Byte[] buffer, int offset, int count) => throw null;\n public override int ReadByte() => throw null;\n public override int ReadTimeout { get => throw null; set => throw null; }\n public override int WriteTimeout { get => throw null; set => throw null; }\n public override void EndWrite(System.IAsyncResult asyncResult) => throw null;\n public override void Flush() => throw null;\n public override void SetLength(System.Int64 value) => throw null;\n public override void Write(System.Byte[] buffer, int offset, int count) => throw null;\n}\n\n// Generated from `System.Net.Security.TlsCipherSuite` in `System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic enum TlsCipherSuite\n{\n}\n\n}\n}\nnamespace Runtime\n{\nnamespace Serialization\n{\n// Generated from `System.Runtime.Serialization.DataContractAttribute` in `System.Runtime.Serialization.Primitives, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DataContractAttribute : System.Attribute\n{\n public DataContractAttribute() => throw null;\n}\n\n// Generated from `System.Runtime.Serialization.DataMemberAttribute` in `System.Runtime.Serialization.Primitives, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DataMemberAttribute : System.Attribute\n{\n public DataMemberAttribute() => throw null;\n}\n\n}\n}\nnamespace Text\n{\nnamespace RegularExpressions\n{\n// Generated from `System.Text.RegularExpressions.Capture` in `System.Text.RegularExpressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Capture\n{\n public override string ToString() => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.CollectionDebuggerProxy<>` in `System.Text.RegularExpressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass CollectionDebuggerProxy\n{\n}\n\n// Generated from `System.Text.RegularExpressions.GroupCollection` in `System.Text.RegularExpressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class GroupCollection : System.Collections.IList, System.Collections.IEnumerable, System.Collections.ICollection, System.Collections.Generic.IReadOnlyList, System.Collections.Generic.IReadOnlyDictionary, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IList, System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerable>, System.Collections.Generic.ICollection\n{\n System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() => throw null;\n System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null;\n System.Text.RegularExpressions.Group this[int index] { get => throw null; set => throw null; }\n bool System.Collections.Generic.ICollection.Contains(System.Text.RegularExpressions.Group item) => throw null;\n bool System.Collections.Generic.ICollection.Remove(System.Text.RegularExpressions.Group item) => throw null;\n bool System.Collections.IList.Contains(object value) => throw null;\n bool System.Collections.IList.IsFixedSize { get => throw null; }\n int System.Collections.Generic.IList.IndexOf(System.Text.RegularExpressions.Group item) => throw null;\n int System.Collections.IList.Add(object value) => throw null;\n int System.Collections.IList.IndexOf(object value) => throw null;\n object this[int index] { get => throw null; set => throw null; }\n public System.Collections.Generic.IEnumerable Values { get => throw null; }\n public System.Collections.Generic.IEnumerable Keys { get => throw null; }\n public System.Collections.IEnumerator GetEnumerator() => throw null;\n public System.Text.RegularExpressions.Group this[string groupname] { get => throw null; }\n public bool ContainsKey(string key) => throw null;\n public bool IsReadOnly { get => throw null; }\n public bool IsSynchronized { get => throw null; }\n public bool TryGetValue(string key, out System.Text.RegularExpressions.Group value) => throw null;\n public int Count { get => throw null; }\n public object SyncRoot { get => throw null; }\n public void CopyTo(System.Array array, int arrayIndex) => throw null;\n public void CopyTo(System.Text.RegularExpressions.Group[] array, int arrayIndex) => throw null;\n void System.Collections.Generic.ICollection.Add(System.Text.RegularExpressions.Group item) => throw null;\n void System.Collections.Generic.ICollection.Clear() => throw null;\n void System.Collections.Generic.IList.Insert(int index, System.Text.RegularExpressions.Group item) => throw null;\n void System.Collections.Generic.IList.RemoveAt(int index) => throw null;\n void System.Collections.IList.Clear() => throw null;\n void System.Collections.IList.Insert(int index, object value) => throw null;\n void System.Collections.IList.Remove(object value) => throw null;\n void System.Collections.IList.RemoveAt(int index) => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.Group` in `System.Text.RegularExpressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Group : System.Text.RegularExpressions.Capture\n{\n}\n\n// Generated from `System.Text.RegularExpressions.Match` in `System.Text.RegularExpressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Match : System.Text.RegularExpressions.Group\n{\n}\n\n// Generated from `System.Text.RegularExpressions.RegexOptions` in `System.Text.RegularExpressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\n[System.Flags]\npublic enum RegexOptions\n{\n IgnoreCase,\n}\n\n// Generated from `System.Text.RegularExpressions.Regex` in `System.Text.RegularExpressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Regex : System.Runtime.Serialization.ISerializable\n{\n public Regex(string pattern) => throw null;\n public Regex(string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) => throw null;\n public System.Text.RegularExpressions.Match Match(string input) => throw null;\n public override string ToString() => throw null;\n public static System.Text.RegularExpressions.Match Match(string input, string pattern) => throw null;\n public static System.Text.RegularExpressions.Match Match(string input, string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) => throw null;\n public string Replace(string input, string replacement) => throw null;\n void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo si, System.Runtime.Serialization.StreamingContext context) => throw null;\n}\n\n}\n}\nnamespace Timers\n{\n// Generated from `System.Timers.TimersDescriptionAttribute` in `System.ComponentModel.TypeConverter, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TimersDescriptionAttribute\n{\n public TimersDescriptionAttribute(string description) => throw null;\n}\n\n}\nnamespace Windows\n{\nnamespace Markup\n{\n// Generated from `System.Windows.Markup.ValueSerializerAttribute` in `System.ObjectModel, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ValueSerializerAttribute : System.Attribute\n{\n public ValueSerializerAttribute(System.Type valueSerializerType) => throw null;\n public ValueSerializerAttribute(string valueSerializerTypeName) => throw null;\n}\n\n}\n}\n}\n | +| // This file contains auto-generated code.\n// original-extractor-options: /r:System.Text.RegularExpressions.dll /r:System.Collections.Specialized.dll /r:System.Net.dll /r:System.Web.dll /r:System.Net.HttpListener.dll /r:System.Collections.Specialized.dll /r:System.Private.Uri.dll /r:System.Runtime.Extensions.dll /r:System.Linq.Parallel.dll /r:System.Collections.Concurrent.dll /r:System.Linq.Expressions.dll /r:System.Collections.dll /r:System.Linq.Queryable.dll /r:System.Linq.dll /r:System.Collections.NonGeneric.dll /r:System.ObjectModel.dll /r:System.ComponentModel.TypeConverter.dll /r:System.IO.Compression.dll /r:System.IO.Pipes.dll /r:System.Net.Primitives.dll /r:System.Net.Security.dll /r:System.Security.Cryptography.Primitives.dll /r:System.Text.RegularExpressions.dll ${testdir}/../../resources/stubs/System.Web.cs /r:System.Runtime.Serialization.Primitives.dll\n\nnamespace System\n{\n// Generated from `System.Uri` in `System.Private.Uri, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Uri : System.Runtime.Serialization.ISerializable\n{\n public override bool Equals(object comparand) => throw null;\n public override int GetHashCode() => throw null;\n public override string ToString() => throw null;\n void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) => throw null;\n}\n\nnamespace Collections\n{\n// Generated from `System.Collections.Queue` in `System.Collections.NonGeneric, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Queue : System.ICloneable, System.Collections.IEnumerable, System.Collections.ICollection\n{\n public virtual System.Collections.IEnumerator GetEnumerator() => throw null;\n public virtual bool IsSynchronized { get => throw null; }\n public virtual int Count { get => throw null; }\n public virtual object Clone() => throw null;\n public virtual object SyncRoot { get => throw null; }\n public virtual void CopyTo(System.Array array, int index) => throw null;\n}\n\n// Generated from `System.Collections.SortedList` in `System.Collections.NonGeneric, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class SortedList : System.ICloneable, System.Collections.IEnumerable, System.Collections.IDictionary, System.Collections.ICollection\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public virtual System.Collections.ICollection Keys { get => throw null; }\n public virtual System.Collections.ICollection Values { get => throw null; }\n public virtual System.Collections.IDictionaryEnumerator GetEnumerator() => throw null;\n public virtual bool Contains(object key) => throw null;\n public virtual bool IsFixedSize { get => throw null; }\n public virtual bool IsReadOnly { get => throw null; }\n public virtual bool IsSynchronized { get => throw null; }\n public virtual int Count { get => throw null; }\n public virtual object Clone() => throw null;\n public virtual object GetByIndex(int index) => throw null;\n public virtual object SyncRoot { get => throw null; }\n public virtual object this[object key] { get => throw null; set => throw null; }\n public virtual void Add(object key, object value) => throw null;\n public virtual void Clear() => throw null;\n public virtual void CopyTo(System.Array array, int arrayIndex) => throw null;\n public virtual void Remove(object key) => throw null;\n}\n\n// Generated from `System.Collections.Stack` in `System.Collections.NonGeneric, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Stack : System.ICloneable, System.Collections.IEnumerable, System.Collections.ICollection\n{\n public virtual System.Collections.IEnumerator GetEnumerator() => throw null;\n public virtual bool IsSynchronized { get => throw null; }\n public virtual int Count { get => throw null; }\n public virtual object Clone() => throw null;\n public virtual object SyncRoot { get => throw null; }\n public virtual void CopyTo(System.Array array, int index) => throw null;\n}\n\nnamespace Concurrent\n{\n// Generated from `System.Collections.Concurrent.BlockingCollection<>` in `System.Collections.Concurrent, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class BlockingCollection : System.IDisposable, System.Collections.IEnumerable, System.Collections.ICollection, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IEnumerable\n{\n System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null;\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n public int Count { get => throw null; }\n public void Dispose() => throw null;\n void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null;\n}\n\n// Generated from `System.Collections.Concurrent.BlockingCollectionDebugView<>` in `System.Collections.Concurrent, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass BlockingCollectionDebugView\n{\n}\n\n// Generated from `System.Collections.Concurrent.IDictionaryDebugView<,>` in `System.Collections.Concurrent, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass IDictionaryDebugView\n{\n}\n\n}\nnamespace Generic\n{\n// Generated from `System.Collections.Generic.CollectionDebugView<>` in `System.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass CollectionDebugView\n{\n}\n\n// Generated from `System.Collections.Generic.DictionaryDebugView<,>` in `System.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass DictionaryDebugView\n{\n}\n\n// Generated from `System.Collections.Generic.QueueDebugView<>` in `System.Collections, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass QueueDebugView\n{\n}\n\n// Generated from `System.Collections.Generic.SortedSet<>` in `System.Collections, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class SortedSet : System.Runtime.Serialization.ISerializable, System.Runtime.Serialization.IDeserializationCallback, System.Collections.IEnumerable, System.Collections.ICollection, System.Collections.Generic.ISet, System.Collections.Generic.IReadOnlySet, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.ICollection\n{\n System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null;\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n bool System.Collections.Generic.ICollection.IsReadOnly { get => throw null; }\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n public bool Add(T item) => throw null;\n public bool IsProperSubsetOf(System.Collections.Generic.IEnumerable other) => throw null;\n public bool IsProperSupersetOf(System.Collections.Generic.IEnumerable other) => throw null;\n public bool IsSubsetOf(System.Collections.Generic.IEnumerable other) => throw null;\n public bool IsSupersetOf(System.Collections.Generic.IEnumerable other) => throw null;\n public bool Overlaps(System.Collections.Generic.IEnumerable other) => throw null;\n public bool Remove(T item) => throw null;\n public bool SetEquals(System.Collections.Generic.IEnumerable other) => throw null;\n public int Count { get => throw null; }\n public virtual bool Contains(T item) => throw null;\n public virtual void Clear() => throw null;\n public virtual void IntersectWith(System.Collections.Generic.IEnumerable other) => throw null;\n public void CopyTo(T[] array, int index) => throw null;\n public void ExceptWith(System.Collections.Generic.IEnumerable other) => throw null;\n public void SymmetricExceptWith(System.Collections.Generic.IEnumerable other) => throw null;\n public void UnionWith(System.Collections.Generic.IEnumerable other) => throw null;\n void System.Collections.Generic.ICollection.Add(T item) => throw null;\n void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null;\n void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) => throw null;\n void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null;\n}\n\n// Generated from `System.Collections.Generic.Stack<>` in `System.Collections, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Stack : System.Collections.IEnumerable, System.Collections.ICollection, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IEnumerable\n{\n System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null;\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n public T Peek() => throw null;\n public int Count { get => throw null; }\n void System.Collections.ICollection.CopyTo(System.Array array, int arrayIndex) => throw null;\n}\n\n// Generated from `System.Collections.Generic.StackDebugView<>` in `System.Collections, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass StackDebugView\n{\n}\n\n}\nnamespace Specialized\n{\n// Generated from `System.Collections.Specialized.NameObjectCollectionBase` in `System.Collections.Specialized, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract public class NameObjectCollectionBase : System.Runtime.Serialization.ISerializable, System.Runtime.Serialization.IDeserializationCallback, System.Collections.IEnumerable, System.Collections.ICollection\n{\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n public virtual System.Collections.IEnumerator GetEnumerator() => throw null;\n public virtual int Count { get => throw null; }\n public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null;\n public virtual void OnDeserialization(object sender) => throw null;\n void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null;\n}\n\n// Generated from `System.Collections.Specialized.NameValueCollection` in `System.Collections.Specialized, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class NameValueCollection : System.Collections.Specialized.NameObjectCollectionBase\n{\n public string this[string name] { get => throw null; set => throw null; }\n}\n\n}\n}\nnamespace ComponentModel\n{\n// Generated from `System.ComponentModel.ComponentConverter` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ComponentConverter : System.ComponentModel.ReferenceConverter\n{\n}\n\n// Generated from `System.ComponentModel.DefaultEventAttribute` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DefaultEventAttribute : System.Attribute\n{\n public DefaultEventAttribute(string name) => throw null;\n public override bool Equals(object obj) => throw null;\n public override int GetHashCode() => throw null;\n}\n\n// Generated from `System.ComponentModel.DefaultPropertyAttribute` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DefaultPropertyAttribute : System.Attribute\n{\n public DefaultPropertyAttribute(string name) => throw null;\n public override bool Equals(object obj) => throw null;\n public override int GetHashCode() => throw null;\n}\n\n// Generated from `System.ComponentModel.INotifyPropertyChanged` in `System.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface INotifyPropertyChanged\n{\n}\n\n// Generated from `System.ComponentModel.ReferenceConverter` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ReferenceConverter : System.ComponentModel.TypeConverter\n{\n}\n\n// Generated from `System.ComponentModel.TypeConverterAttribute` in `System.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TypeConverterAttribute : System.Attribute\n{\n public TypeConverterAttribute() => throw null;\n public TypeConverterAttribute(System.Type type) => throw null;\n public TypeConverterAttribute(string typeName) => throw null;\n public override bool Equals(object obj) => throw null;\n public override int GetHashCode() => throw null;\n}\n\n// Generated from `System.ComponentModel.TypeConverter` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TypeConverter\n{\n}\n\n// Generated from `System.ComponentModel.TypeDescriptionProviderAttribute` in `System.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TypeDescriptionProviderAttribute : System.Attribute\n{\n public TypeDescriptionProviderAttribute(System.Type type) => throw null;\n public TypeDescriptionProviderAttribute(string typeName) => throw null;\n}\n\n// Generated from `System.ComponentModel.TypeDescriptionProvider` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract public class TypeDescriptionProvider\n{\n}\n\n// Generated from `System.ComponentModel.TypeDescriptor` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TypeDescriptor\n{\n}\n\nnamespace Design\n{\n// Generated from `System.ComponentModel.Design.DesignerOptionService` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract public class DesignerOptionService : System.ComponentModel.Design.IDesignerOptionService\n{\n}\n\n// Generated from `System.ComponentModel.Design.IDesignerOptionService` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface IDesignerOptionService\n{\n}\n\n}\n}\nnamespace Dynamic\n{\n// Generated from `System.Dynamic.DynamicMetaObject` in `System.Linq.Expressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DynamicMetaObject\n{\n}\n\n// Generated from `System.Dynamic.ExpandoObject` in `System.Linq.Expressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ExpandoObject : System.Dynamic.IDynamicMetaObjectProvider, System.ComponentModel.INotifyPropertyChanged, System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IDictionary, System.Collections.Generic.ICollection>\n{\n System.Collections.Generic.ICollection System.Collections.Generic.IDictionary.Values { get => throw null; }\n System.Collections.Generic.ICollection System.Collections.Generic.IDictionary.Keys { get => throw null; }\n System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() => throw null;\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n bool System.Collections.Generic.ICollection>.Contains(System.Collections.Generic.KeyValuePair item) => throw null;\n bool System.Collections.Generic.ICollection>.IsReadOnly { get => throw null; }\n bool System.Collections.Generic.ICollection>.Remove(System.Collections.Generic.KeyValuePair item) => throw null;\n bool System.Collections.Generic.IDictionary.ContainsKey(string key) => throw null;\n bool System.Collections.Generic.IDictionary.Remove(string key) => throw null;\n bool System.Collections.Generic.IDictionary.TryGetValue(string key, out object value) => throw null;\n int System.Collections.Generic.ICollection>.Count { get => throw null; }\n object this[string key] { get => throw null; set => throw null; }\n void System.Collections.Generic.ICollection>.Add(System.Collections.Generic.KeyValuePair item) => throw null;\n void System.Collections.Generic.ICollection>.Clear() => throw null;\n void System.Collections.Generic.ICollection>.CopyTo(System.Collections.Generic.KeyValuePair[] array, int arrayIndex) => throw null;\n void System.Collections.Generic.IDictionary.Add(string key, object value) => throw null;\n}\n\n// Generated from `System.Dynamic.IDynamicMetaObjectProvider` in `System.Linq.Expressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface IDynamicMetaObjectProvider\n{\n}\n\nnamespace Utils\n{\n// Generated from `System.Dynamic.Utils.ListProvider<>` in `System.Linq.Expressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract class ListProvider : System.Collections.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IEnumerable, System.Collections.Generic.ICollection where T: class\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public System.Collections.Generic.IEnumerator GetEnumerator() => throw null;\n public T this[int index] { get => throw null; set => throw null; }\n public bool Contains(T item) => throw null;\n public bool IsReadOnly { get => throw null; }\n public bool Remove(T item) => throw null;\n public int Count { get => throw null; }\n public int IndexOf(T item) => throw null;\n public void Add(T item) => throw null;\n public void Clear() => throw null;\n public void CopyTo(T[] array, int index) => throw null;\n public void Insert(int index, T item) => throw null;\n public void RemoveAt(int index) => throw null;\n}\n\n}\n}\nnamespace IO\n{\nnamespace Compression\n{\n// Generated from `System.IO.Compression.DeflateStream` in `System.IO.Compression, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089`\npublic class DeflateStream : System.IO.Stream\n{\n protected override void Dispose(bool disposing) => throw null;\n public override System.IAsyncResult BeginRead(System.Byte[] buffer, int offset, int count, System.AsyncCallback asyncCallback, object asyncState) => throw null;\n public override System.IAsyncResult BeginWrite(System.Byte[] array, int offset, int count, System.AsyncCallback asyncCallback, object asyncState) => throw null;\n public override System.Int64 Length { get => throw null; }\n public override System.Int64 Position { get => throw null; set => throw null; }\n public override System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin) => throw null;\n public override System.Threading.Tasks.Task CopyToAsync(System.IO.Stream destination, int bufferSize, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.Task WriteAsync(System.Byte[] array, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.Task ReadAsync(System.Byte[] array, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.ValueTask DisposeAsync() => throw null;\n public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.ValueTask ReadAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken) => throw null;\n public override bool CanRead { get => throw null; }\n public override bool CanSeek { get => throw null; }\n public override bool CanWrite { get => throw null; }\n public override int EndRead(System.IAsyncResult asyncResult) => throw null;\n public override int Read(System.Byte[] array, int offset, int count) => throw null;\n public override int Read(System.Span buffer) => throw null;\n public override int ReadByte() => throw null;\n public override void CopyTo(System.IO.Stream destination, int bufferSize) => throw null;\n public override void EndWrite(System.IAsyncResult asyncResult) => throw null;\n public override void Flush() => throw null;\n public override void SetLength(System.Int64 value) => throw null;\n public override void Write(System.Byte[] array, int offset, int count) => throw null;\n public override void Write(System.ReadOnlySpan buffer) => throw null;\n}\n\n}\n}\nnamespace Linq\n{\n// Generated from `System.Linq.Enumerable` in `System.Linq, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nstatic public class Enumerable\n{\n public static System.Collections.Generic.IEnumerable Select(this System.Collections.Generic.IEnumerable source, System.Func selector) => throw null;\n}\n\n// Generated from `System.Linq.Grouping<,>` in `System.Linq, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Grouping : System.Linq.IGrouping, System.Collections.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IEnumerable, System.Collections.Generic.ICollection\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n TElement this[int index] { get => throw null; set => throw null; }\n bool System.Collections.Generic.ICollection.Contains(TElement item) => throw null;\n bool System.Collections.Generic.ICollection.IsReadOnly { get => throw null; }\n bool System.Collections.Generic.ICollection.Remove(TElement item) => throw null;\n int System.Collections.Generic.ICollection.Count { get => throw null; }\n int System.Collections.Generic.IList.IndexOf(TElement item) => throw null;\n public System.Collections.Generic.IEnumerator GetEnumerator() => throw null;\n void System.Collections.Generic.ICollection.Add(TElement item) => throw null;\n void System.Collections.Generic.ICollection.Clear() => throw null;\n void System.Collections.Generic.ICollection.CopyTo(TElement[] array, int arrayIndex) => throw null;\n void System.Collections.Generic.IList.Insert(int index, TElement item) => throw null;\n void System.Collections.Generic.IList.RemoveAt(int index) => throw null;\n}\n\n// Generated from `System.Linq.IGrouping<,>` in `System.Linq, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface IGrouping : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable\n{\n}\n\n// Generated from `System.Linq.IIListProvider<>` in `System.Linq, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\ninterface IIListProvider : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable\n{\n}\n\n// Generated from `System.Linq.ILookup<,>` in `System.Linq, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface ILookup : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>\n{\n}\n\n// Generated from `System.Linq.IOrderedEnumerable<>` in `System.Linq, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface IOrderedEnumerable : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable\n{\n}\n\n// Generated from `System.Linq.IPartition<>` in `System.Linq, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\ninterface IPartition : System.Linq.IIListProvider, System.Collections.IEnumerable, System.Collections.Generic.IEnumerable\n{\n}\n\n// Generated from `System.Linq.IQueryable` in `System.Linq.Expressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface IQueryable : System.Collections.IEnumerable\n{\n}\n\n// Generated from `System.Linq.Lookup<,>` in `System.Linq, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Lookup : System.Linq.ILookup, System.Linq.IIListProvider>, System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null;\n}\n\n// Generated from `System.Linq.OrderedEnumerable<>` in `System.Linq, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract class OrderedEnumerable : System.Linq.IPartition, System.Linq.IOrderedEnumerable, System.Linq.IIListProvider, System.Collections.IEnumerable, System.Collections.Generic.IEnumerable\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public System.Collections.Generic.IEnumerator GetEnumerator() => throw null;\n}\n\n// Generated from `System.Linq.ParallelEnumerable` in `System.Linq.Parallel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nstatic public class ParallelEnumerable\n{\n public static System.Linq.ParallelQuery AsParallel(this System.Collections.IEnumerable source) => throw null;\n}\n\n// Generated from `System.Linq.ParallelQuery<>` in `System.Linq.Parallel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ParallelQuery : System.Linq.ParallelQuery, System.Collections.IEnumerable, System.Collections.Generic.IEnumerable\n{\n public virtual System.Collections.Generic.IEnumerator GetEnumerator() => throw null;\n}\n\n// Generated from `System.Linq.ParallelQuery` in `System.Linq.Parallel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ParallelQuery : System.Collections.IEnumerable\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n}\n\n// Generated from `System.Linq.Queryable` in `System.Linq.Queryable, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nstatic public class Queryable\n{\n public static System.Linq.IQueryable AsQueryable(this System.Collections.IEnumerable source) => throw null;\n}\n\n// Generated from `System.Linq.SystemLinq_GroupingDebugView<,>` in `System.Linq, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass SystemLinq_GroupingDebugView\n{\n}\n\n// Generated from `System.Linq.SystemLinq_LookupDebugView<,>` in `System.Linq, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass SystemLinq_LookupDebugView\n{\n}\n\nnamespace Expressions\n{\n// Generated from `System.Linq.Expressions.BlockExpressionList` in `System.Linq.Expressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass BlockExpressionList : System.Collections.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IEnumerable, System.Collections.Generic.ICollection\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public System.Collections.Generic.IEnumerator GetEnumerator() => throw null;\n public System.Linq.Expressions.Expression this[int index] { get => throw null; set => throw null; }\n public bool Contains(System.Linq.Expressions.Expression item) => throw null;\n public bool IsReadOnly { get => throw null; }\n public bool Remove(System.Linq.Expressions.Expression item) => throw null;\n public int Count { get => throw null; }\n public int IndexOf(System.Linq.Expressions.Expression item) => throw null;\n public void Add(System.Linq.Expressions.Expression item) => throw null;\n public void Clear() => throw null;\n public void CopyTo(System.Linq.Expressions.Expression[] array, int index) => throw null;\n public void Insert(int index, System.Linq.Expressions.Expression item) => throw null;\n public void RemoveAt(int index) => throw null;\n}\n\n// Generated from `System.Linq.Expressions.Expression` in `System.Linq.Expressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract public class Expression\n{\n public override string ToString() => throw null;\n}\n\n// Generated from `System.Linq.Expressions.ParameterExpression` in `System.Linq.Expressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ParameterExpression : System.Linq.Expressions.Expression\n{\n}\n\nnamespace Compiler\n{\n// Generated from `System.Linq.Expressions.Compiler.ParameterList` in `System.Linq.Expressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass ParameterList : System.Collections.IEnumerable, System.Collections.Generic.IReadOnlyList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IEnumerable\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public System.Collections.Generic.IEnumerator GetEnumerator() => throw null;\n public System.Linq.Expressions.ParameterExpression this[int index] { get => throw null; }\n public int Count { get => throw null; }\n}\n\n}\nnamespace Interpreter\n{\n// Generated from `System.Linq.Expressions.Interpreter.InstructionArray` in `System.Linq.Expressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nstruct InstructionArray\n{\n}\n\n// Generated from `System.Linq.Expressions.Interpreter.InstructionList` in `System.Linq.Expressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass InstructionList\n{\n}\n\n// Generated from `System.Linq.Expressions.Interpreter.InterpretedFrameInfo` in `System.Linq.Expressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nstruct InterpretedFrameInfo\n{\n public override string ToString() => throw null;\n}\n\n// Generated from `System.Linq.Expressions.Interpreter.InterpretedFrame` in `System.Linq.Expressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass InterpretedFrame\n{\n}\n\n}\n}\nnamespace Parallel\n{\n// Generated from `System.Linq.Parallel.ListChunk<>` in `System.Linq.Parallel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass ListChunk : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public System.Collections.Generic.IEnumerator GetEnumerator() => throw null;\n}\n\n// Generated from `System.Linq.Parallel.Lookup<,>` in `System.Linq.Parallel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass Lookup : System.Linq.ILookup, System.Collections.IEnumerable, System.Collections.Generic.IEnumerable>\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null;\n}\n\n// Generated from `System.Linq.Parallel.PartitionerQueryOperator<>` in `System.Linq.Parallel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass PartitionerQueryOperator : System.Linq.Parallel.QueryOperator\n{\n}\n\n// Generated from `System.Linq.Parallel.QueryOperator<>` in `System.Linq.Parallel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract class QueryOperator : System.Linq.ParallelQuery\n{\n public override System.Collections.Generic.IEnumerator GetEnumerator() => throw null;\n}\n\n// Generated from `System.Linq.Parallel.QueryResults<>` in `System.Linq.Parallel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract class QueryResults : System.Collections.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IEnumerable, System.Collections.Generic.ICollection\n{\n System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null;\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n bool System.Collections.Generic.ICollection.Contains(T item) => throw null;\n bool System.Collections.Generic.ICollection.IsReadOnly { get => throw null; }\n bool System.Collections.Generic.ICollection.Remove(T item) => throw null;\n int System.Collections.Generic.IList.IndexOf(T item) => throw null;\n public T this[int index] { get => throw null; set => throw null; }\n public int Count { get => throw null; }\n void System.Collections.Generic.ICollection.Add(T item) => throw null;\n void System.Collections.Generic.ICollection.Clear() => throw null;\n void System.Collections.Generic.ICollection.CopyTo(T[] array, int arrayIndex) => throw null;\n void System.Collections.Generic.IList.Insert(int index, T item) => throw null;\n void System.Collections.Generic.IList.RemoveAt(int index) => throw null;\n}\n\n// Generated from `System.Linq.Parallel.ZipQueryOperator<,,>` in `System.Linq.Parallel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass ZipQueryOperator : System.Linq.Parallel.QueryOperator\n{\n}\n\n}\n}\nnamespace Net\n{\n// Generated from `System.Net.CookieCollection` in `System.Net.Primitives, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class CookieCollection : System.Collections.IEnumerable, System.Collections.ICollection, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.ICollection\n{\n System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null;\n public System.Collections.IEnumerator GetEnumerator() => throw null;\n public bool Contains(System.Net.Cookie cookie) => throw null;\n public bool IsReadOnly { get => throw null; }\n public bool IsSynchronized { get => throw null; }\n public bool Remove(System.Net.Cookie cookie) => throw null;\n public int Count { get => throw null; }\n public object SyncRoot { get => throw null; }\n public void Add(System.Net.Cookie cookie) => throw null;\n public void Clear() => throw null;\n public void CopyTo(System.Array array, int index) => throw null;\n public void CopyTo(System.Net.Cookie[] array, int index) => throw null;\n}\n\n// Generated from `System.Net.Cookie` in `System.Net.Primitives, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Cookie\n{\n public override bool Equals(object comparand) => throw null;\n public override int GetHashCode() => throw null;\n public override string ToString() => throw null;\n}\n\n// Generated from `System.Net.StreamFramer` in `System.Net.Security, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass StreamFramer\n{\n}\n\nnamespace Security\n{\n// Generated from `System.Net.Security.AuthenticatedStream` in `System.Net.Security, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract public class AuthenticatedStream : System.IO.Stream\n{\n protected override void Dispose(bool disposing) => throw null;\n public override System.Threading.Tasks.ValueTask DisposeAsync() => throw null;\n}\n\n// Generated from `System.Net.Security.CipherSuitesPolicy` in `System.Net.Security, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class CipherSuitesPolicy\n{\n}\n\n// Generated from `System.Net.Security.NegotiateStream` in `System.Net.Security, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class NegotiateStream : System.Net.Security.AuthenticatedStream\n{\n protected override void Dispose(bool disposing) => throw null;\n public override System.IAsyncResult BeginRead(System.Byte[] buffer, int offset, int count, System.AsyncCallback asyncCallback, object asyncState) => throw null;\n public override System.IAsyncResult BeginWrite(System.Byte[] buffer, int offset, int count, System.AsyncCallback asyncCallback, object asyncState) => throw null;\n public override System.Int64 Length { get => throw null; }\n public override System.Int64 Position { get => throw null; set => throw null; }\n public override System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin) => throw null;\n public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.Task WriteAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.Task ReadAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.ValueTask DisposeAsync() => throw null;\n public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.ValueTask ReadAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken) => throw null;\n public override bool CanRead { get => throw null; }\n public override bool CanSeek { get => throw null; }\n public override bool CanTimeout { get => throw null; }\n public override bool CanWrite { get => throw null; }\n public override int EndRead(System.IAsyncResult asyncResult) => throw null;\n public override int Read(System.Byte[] buffer, int offset, int count) => throw null;\n public override int ReadTimeout { get => throw null; set => throw null; }\n public override int WriteTimeout { get => throw null; set => throw null; }\n public override void EndWrite(System.IAsyncResult asyncResult) => throw null;\n public override void Flush() => throw null;\n public override void SetLength(System.Int64 value) => throw null;\n public override void Write(System.Byte[] buffer, int offset, int count) => throw null;\n}\n\n// Generated from `System.Net.Security.SslStream` in `System.Net.Security, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class SslStream : System.Net.Security.AuthenticatedStream\n{\n protected override void Dispose(bool disposing) => throw null;\n public override System.IAsyncResult BeginRead(System.Byte[] buffer, int offset, int count, System.AsyncCallback asyncCallback, object asyncState) => throw null;\n public override System.IAsyncResult BeginWrite(System.Byte[] buffer, int offset, int count, System.AsyncCallback asyncCallback, object asyncState) => throw null;\n public override System.Int64 Length { get => throw null; }\n public override System.Int64 Position { get => throw null; set => throw null; }\n public override System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin) => throw null;\n public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.Task WriteAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.Task ReadAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.ValueTask DisposeAsync() => throw null;\n public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.ValueTask ReadAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken) => throw null;\n public override bool CanRead { get => throw null; }\n public override bool CanSeek { get => throw null; }\n public override bool CanTimeout { get => throw null; }\n public override bool CanWrite { get => throw null; }\n public override int EndRead(System.IAsyncResult asyncResult) => throw null;\n public override int Read(System.Byte[] buffer, int offset, int count) => throw null;\n public override int ReadByte() => throw null;\n public override int ReadTimeout { get => throw null; set => throw null; }\n public override int WriteTimeout { get => throw null; set => throw null; }\n public override void EndWrite(System.IAsyncResult asyncResult) => throw null;\n public override void Flush() => throw null;\n public override void SetLength(System.Int64 value) => throw null;\n public override void Write(System.Byte[] buffer, int offset, int count) => throw null;\n}\n\n// Generated from `System.Net.Security.TlsCipherSuite` in `System.Net.Security, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic enum TlsCipherSuite\n{\n}\n\n}\n}\nnamespace Runtime\n{\nnamespace Serialization\n{\n// Generated from `System.Runtime.Serialization.DataContractAttribute` in `System.Runtime.Serialization.Primitives, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DataContractAttribute : System.Attribute\n{\n public DataContractAttribute() => throw null;\n}\n\n// Generated from `System.Runtime.Serialization.DataMemberAttribute` in `System.Runtime.Serialization.Primitives, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DataMemberAttribute : System.Attribute\n{\n public DataMemberAttribute() => throw null;\n}\n\n}\n}\nnamespace Text\n{\nnamespace RegularExpressions\n{\n// Generated from `System.Text.RegularExpressions.Capture` in `System.Text.RegularExpressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Capture\n{\n public override string ToString() => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.CollectionDebuggerProxy<>` in `System.Text.RegularExpressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nclass CollectionDebuggerProxy\n{\n}\n\n// Generated from `System.Text.RegularExpressions.GroupCollection` in `System.Text.RegularExpressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class GroupCollection : System.Collections.IList, System.Collections.IEnumerable, System.Collections.ICollection, System.Collections.Generic.IReadOnlyList, System.Collections.Generic.IReadOnlyDictionary, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IList, System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerable>, System.Collections.Generic.ICollection\n{\n System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() => throw null;\n System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null;\n System.Text.RegularExpressions.Group this[int index] { get => throw null; set => throw null; }\n bool System.Collections.Generic.ICollection.Contains(System.Text.RegularExpressions.Group item) => throw null;\n bool System.Collections.Generic.ICollection.Remove(System.Text.RegularExpressions.Group item) => throw null;\n bool System.Collections.IList.Contains(object value) => throw null;\n bool System.Collections.IList.IsFixedSize { get => throw null; }\n int System.Collections.Generic.IList.IndexOf(System.Text.RegularExpressions.Group item) => throw null;\n int System.Collections.IList.Add(object value) => throw null;\n int System.Collections.IList.IndexOf(object value) => throw null;\n object this[int index] { get => throw null; set => throw null; }\n public System.Collections.Generic.IEnumerable Values { get => throw null; }\n public System.Collections.Generic.IEnumerable Keys { get => throw null; }\n public System.Collections.IEnumerator GetEnumerator() => throw null;\n public System.Text.RegularExpressions.Group this[string groupname] { get => throw null; }\n public bool ContainsKey(string key) => throw null;\n public bool IsReadOnly { get => throw null; }\n public bool IsSynchronized { get => throw null; }\n public bool TryGetValue(string key, out System.Text.RegularExpressions.Group value) => throw null;\n public int Count { get => throw null; }\n public object SyncRoot { get => throw null; }\n public void CopyTo(System.Array array, int arrayIndex) => throw null;\n public void CopyTo(System.Text.RegularExpressions.Group[] array, int arrayIndex) => throw null;\n void System.Collections.Generic.ICollection.Add(System.Text.RegularExpressions.Group item) => throw null;\n void System.Collections.Generic.ICollection.Clear() => throw null;\n void System.Collections.Generic.IList.Insert(int index, System.Text.RegularExpressions.Group item) => throw null;\n void System.Collections.Generic.IList.RemoveAt(int index) => throw null;\n void System.Collections.IList.Clear() => throw null;\n void System.Collections.IList.Insert(int index, object value) => throw null;\n void System.Collections.IList.Remove(object value) => throw null;\n void System.Collections.IList.RemoveAt(int index) => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.Group` in `System.Text.RegularExpressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Group : System.Text.RegularExpressions.Capture\n{\n}\n\n// Generated from `System.Text.RegularExpressions.Match` in `System.Text.RegularExpressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Match : System.Text.RegularExpressions.Group\n{\n}\n\n// Generated from `System.Text.RegularExpressions.RegexOptions` in `System.Text.RegularExpressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\n[System.Flags]\npublic enum RegexOptions\n{\n IgnoreCase,\n}\n\n// Generated from `System.Text.RegularExpressions.Regex` in `System.Text.RegularExpressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Regex : System.Runtime.Serialization.ISerializable\n{\n public Regex(string pattern) => throw null;\n public Regex(string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) => throw null;\n public System.Text.RegularExpressions.Match Match(string input) => throw null;\n public override string ToString() => throw null;\n public static System.Text.RegularExpressions.Match Match(string input, string pattern) => throw null;\n public static System.Text.RegularExpressions.Match Match(string input, string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) => throw null;\n public string Replace(string input, string replacement) => throw null;\n void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo si, System.Runtime.Serialization.StreamingContext context) => throw null;\n}\n\n}\n}\nnamespace Timers\n{\n// Generated from `System.Timers.TimersDescriptionAttribute` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TimersDescriptionAttribute\n{\n public TimersDescriptionAttribute(string description) => throw null;\n}\n\n}\nnamespace Windows\n{\nnamespace Markup\n{\n// Generated from `System.Windows.Markup.ValueSerializerAttribute` in `System.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ValueSerializerAttribute : System.Attribute\n{\n public ValueSerializerAttribute(System.Type valueSerializerType) => throw null;\n public ValueSerializerAttribute(string valueSerializerTypeName) => throw null;\n}\n\n}\n}\n}\n | diff --git a/java/change-notes/2021-02-17-apache-http.md b/java/change-notes/2021-02-17-apache-http.md new file mode 100644 index 00000000000..3397dd37df6 --- /dev/null +++ b/java/change-notes/2021-02-17-apache-http.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added support for the Apache Http components core library (`org.apache.http.*` and `org.apache.hc.core5.*`); adding additional remote flow sources, sinks for the XSS and Open Redirect queries, and additional taint steps. \ No newline at end of file diff --git a/java/change-notes/2021-03-01-fluent-interface-data-flow.md b/java/change-notes/2021-03-01-fluent-interface-data-flow.md new file mode 100644 index 00000000000..f1492afcf31 --- /dev/null +++ b/java/change-notes/2021-03-01-fluent-interface-data-flow.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* The data-flow library now recognises more side-effects of method chaining (e.g. `someObject.setX(clean).setY(tainted).setZ...` having a side-effect on `someObject`), as well as other related circumstances where a function input is directly passed to its output. All queries that use data-flow analysis, including most security queries, may return more results accordingly. diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/SpringImplicitViewManipulation.qhelp b/java/ql/src/experimental/Security/CWE/CWE-094/SpringImplicitViewManipulation.qhelp new file mode 100644 index 00000000000..ffacd8f8b03 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-094/SpringImplicitViewManipulation.qhelp @@ -0,0 +1,4 @@ + + + + diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/SpringImplicitViewManipulation.ql b/java/ql/src/experimental/Security/CWE/CWE-094/SpringImplicitViewManipulation.ql new file mode 100644 index 00000000000..e4ec03ed956 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-094/SpringImplicitViewManipulation.ql @@ -0,0 +1,64 @@ +/** + * @name Spring Implicit View Manipulation + * @description Untrusted input in a Spring View Controller can lead to RCE. + * @kind problem + * @problem.severity error + * @precision high + * @id java/spring-view-manipulation-implicit + * @tags security + * external/cwe/cwe-094 + */ + +import java +import SpringViewManipulationLib + +private predicate canResultInImplicitViewConversion(Method m) { + m.getReturnType() instanceof VoidType + or + m.getReturnType() instanceof MapType + or + m.getReturnType().(RefType).hasQualifiedName("org.springframework.ui", "Model") +} + +private predicate maybeATestMethod(Method m) { + exists(string s | + s = m.getName() or + s = m.getFile().getRelativePath() or + s = m.getDeclaringType().getName() + | + s.matches(["%test%", "%example%", "%exception%"]) + ) +} + +private predicate mayBeExploitable(Method m) { + // There should be a attacker controlled parameter in the URI for the attack to be exploitable. + // This is possible only when there exists a parameter with the Spring `@PathVariable` annotation + // applied to it. + exists(Parameter p | + p = m.getAParameter() and + p.hasAnnotation("org.springframework.web.bind.annotation", "PathVariable") and + // Having a parameter of say type `Long` is non exploitable as Java type + // checking rules are applied prior to view name resolution, rendering the exploit useless. + // hence, here we check for the param type to be a Java `String`. + p.getType() instanceof TypeString and + // Exclude cases where a regex check is applied on a parameter to prevent false positives. + not m.(SpringRequestMappingMethod).getValue().matches("%{%:[%]%}%") + ) and + not maybeATestMethod(m) +} + +from SpringRequestMappingMethod m +where + thymeleafIsUsed() and + mayBeExploitable(m) and + canResultInImplicitViewConversion(m) and + // If there's a parameter of type`HttpServletResponse`, Spring Framework does not interpret + // it as a view name, but just returns this string in HTTP Response preventing exploitation + // This also applies to `@ResponseBody` annotation. + not m.getParameterType(_) instanceof HttpServletResponse and + // A spring request mapping method which does not have response body annotation applied to it + m.getAnAnnotation().getType() instanceof SpringRequestMappingAnnotationType and + not exists(SpringResponseBodyAnnotationType t | t = m.getAnAnnotation().getType()) and + // `@RestController` inherits `@ResponseBody` internally so it should be ignored. + not m.getDeclaringType() instanceof SpringRestController +select m, "This method may be vulnerable to spring view manipulation vulnerabilities" diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewBad.java b/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewBad.java new file mode 100644 index 00000000000..bb8121f7b11 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewBad.java @@ -0,0 +1,17 @@ +@Controller +public class SptingViewManipulationController { + + Logger log = LoggerFactory.getLogger(HelloController.class); + + @GetMapping("/safe/fragment") + public String Fragment(@RequestParam String section) { + // bad as template path is attacker controlled + return "welcome :: " + section; + } + + @GetMapping("/doc/{document}") + public void getDocument(@PathVariable String document) { + // returns void, so view name is taken from URI + log.info("Retrieving " + document); + } +} diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewGood.java b/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewGood.java new file mode 100644 index 00000000000..046150cae95 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewGood.java @@ -0,0 +1,20 @@ +@Controller +public class SptingViewManipulationController { + + Logger log = LoggerFactory.getLogger(HelloController.class); + + @GetMapping("/safe/fragment") + @ResponseBody + public String Fragment(@RequestParam String section) { + // good, as `@ResponseBody` annotation tells Spring + // to process the return values as body, instead of view name + return "welcome :: " + section; + } + + @GetMapping("/safe/doc/{document}") + public void getDocument(@PathVariable String document, HttpServletResponse response) { + // good as `HttpServletResponse param tells Spring that the response is already + // processed. + log.info("Retrieving " + document); // FP + } +} diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewManipulation.qhelp b/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewManipulation.qhelp new file mode 100644 index 00000000000..dadd20dfdb7 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewManipulation.qhelp @@ -0,0 +1,50 @@ + + + + +

    + The Spring Expression Language (SpEL) is a powerful expression language + provided by Spring Framework. The language offers many features + including invocation of methods available in the JVM. +

    +

    + An unrestricted view name manipulation vulnerability in Spring Framework could lead to attacker-controlled arbitary SpEL expressions being evaluated using attacker-controlled data, which may in turn allow an attacker to run arbitrary code. +

    +

    + Note: two related variants of this problem are detected by different queries, `java/spring-view-manipulation` and `java/spring-view-manipulation-implicit`. The first detects taint flow problems where the return types is always String. While the latter, `java/spring-view-manipulation-implicit` detects cases where the request mapping method has a non-string return type such as void. +

    +
    + + +

    + In general, using user input to determine Spring view name should be avoided. + If user input must be included in the expression, the controller can be annotated by + a @ReponseBody annotation. In this case, Spring Framework does not interpret + it as a view name, but just returns this string in HTTP Response. The same applies to using + a @RestController annotation on a class, as internally it inherits @ResponseBody. +

    +
    + + +

    + In the following example, the Fragment method uses an externally controlled variable section to generate the view name. Hence, it is vulnerable to Spring View Manipulation attacks. +

    + +

    + This can be easily prevented by using the ResponseBody annotation which marks the reponse is already processed preventing exploitation of Spring View Manipulation vulnerabilities. Alternatively, this can also be fixed by adding a HttpServletResponse parameter to the method definition as shown in the example below. +

    + +
    + + +
  • + Veracode Research : Spring View Manipulation +
  • +
  • + Spring Framework Reference Documentation: Spring Expression Language (SpEL) +
  • +
  • + OWASP: Expression Language Injection +
  • +
    +
    diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewManipulation.ql b/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewManipulation.ql new file mode 100644 index 00000000000..3c490e6bf68 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewManipulation.ql @@ -0,0 +1,21 @@ +/** + * @name Spring View Manipulation + * @description Untrusted input in a Spring View can lead to RCE. + * @kind path-problem + * @problem.severity error + * @precision high + * @id java/spring-view-manipulation + * @tags security + * external/cwe/cwe-094 + */ + +import java +import SpringViewManipulationLib +import DataFlow::PathGraph + +from DataFlow::PathNode source, DataFlow::PathNode sink, SpringViewManipulationConfig conf +where + thymeleafIsUsed() and + conf.hasFlowPath(source, sink) +select sink.getNode(), source, sink, "Potential Spring Expression Language injection from $@.", + source.getNode(), "this user input" diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewManipulationLib.qll b/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewManipulationLib.qll new file mode 100644 index 00000000000..b61d64ba7e1 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewManipulationLib.qll @@ -0,0 +1,140 @@ +/** + * Provides classes for reasoning about Spring View Manipulation vulnerabilities + */ + +import java +import semmle.code.java.dataflow.FlowSources +import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.frameworks.spring.Spring +import SpringFrameworkLib + +/** Holds if `Thymeleaf` templating engine is used in the project. */ +predicate thymeleafIsUsed() { + exists(Pom p | + p.getADependency().getArtifact().getValue() in [ + "spring-boot-starter-thymeleaf", "thymeleaf-spring4", "springmvc-xml-thymeleaf", + "thymeleaf-spring5" + ] + ) + or + exists(SpringBean b | b.getClassNameRaw().matches("org.thymeleaf.spring%")) +} + +/** Models methods from the `javax.portlet.RenderState` package which return data from externally controlled sources. */ +class PortletRenderRequestMethod extends Method { + PortletRenderRequestMethod() { + exists(RefType c, Interface t | + c.extendsOrImplements*(t) and + t.hasQualifiedName("javax.portlet", "RenderState") and + this = c.getAMethod() + | + this.hasName([ + "getCookies", "getParameter", "getRenderParameters", "getParameterNames", + "getParameterValues", "getParameterMap" + ]) + ) + } +} + +/** + * A taint-tracking configuration for unsafe user input + * that can lead to Spring View Manipulation vulnerabilities. + */ +class SpringViewManipulationConfig extends TaintTracking::Configuration { + SpringViewManipulationConfig() { this = "Spring View Manipulation Config" } + + override predicate isSource(DataFlow::Node source) { + source instanceof RemoteFlowSource or + source instanceof WebRequestSource or + source.asExpr().(MethodAccess).getMethod() instanceof PortletRenderRequestMethod + } + + override predicate isSink(DataFlow::Node sink) { sink instanceof SpringViewManipulationSink } + + override predicate isSanitizer(DataFlow::Node node) { + // Block flows like + // ``` + // a = "redirect:" + taint` + // ``` + exists(AddExpr e, StringLiteral sl | + node.asExpr() = e.getControlFlowNode().getASuccessor*() and + sl = e.getLeftOperand*() and + sl.getRepresentedString().matches(["redirect:%", "ajaxredirect:%", "forward:%"]) + ) + or + // Block flows like + // ``` + // x.append("redirect:"); + // x.append(tainted()); + // return x.toString(); + // + // "redirect:".concat(taint) + // + // String.format("redirect:%s",taint); + // ``` + exists(Call ca, StringLiteral sl | + ( + sl = ca.getArgument(_) + or + sl = ca.getQualifier() + ) and + ca = getAStringCombiningCall() and + sl.getRepresentedString().matches(["redirect:%", "ajaxredirect:%", "forward:%"]) + | + exists(Call cc | DataFlow::localExprFlow(ca.getQualifier(), cc.getQualifier()) | + cc = node.asExpr() + ) + ) + } +} + +private Call getAStringCombiningCall() { + exists(StringCombiningMethod m | result = m.getAReference()) +} + +abstract private class StringCombiningMethod extends Method { } + +private class AppendableAppendMethod extends StringCombiningMethod { + AppendableAppendMethod() { + exists(RefType t | + t.hasQualifiedName("java.lang", "Appendable") and + this.getDeclaringType().extendsOrImplements*(t) and + this.hasName("append") + ) + } +} + +private class StringConcatMethod extends StringCombiningMethod { + StringConcatMethod() { + this.getDeclaringType() instanceof TypeString and + this.hasName("concat") + } +} + +private class StringFormatMethod extends StringCombiningMethod { + StringFormatMethod() { + this.getDeclaringType() instanceof TypeString and + this.hasName("format") + } +} + +/** + * A sink for Spring View Manipulation vulnerabilities, + */ +class SpringViewManipulationSink extends DataFlow::ExprNode { + SpringViewManipulationSink() { + exists(ReturnStmt r, SpringRequestMappingMethod m | + r.getResult() = this.asExpr() and + m.getBody().getAStmt() = r and + not m.isResponseBody() and + r.getResult().getType() instanceof TypeString + ) + or + exists(ConstructorCall c | c.getConstructedType() instanceof ModelAndView | + this.asExpr() = c.getArgument(0) and + c.getConstructor().getParameterType(0) instanceof TypeString + ) + or + exists(SpringModelAndViewSetViewNameCall c | this.asExpr() = c.getArgument(0)) + } +} diff --git a/java/ql/src/experimental/Security/CWE/CWE-489/EJBMain.ql b/java/ql/src/experimental/Security/CWE/CWE-489/EJBMain.ql index 3c5bac4b710..7723aea9ee2 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-489/EJBMain.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-489/EJBMain.ql @@ -9,13 +9,13 @@ import java import semmle.code.java.J2EE -import MainLib +import TestLib /** The `main` method in an Enterprise Java Bean. */ class EnterpriseBeanMainMethod extends Method { EnterpriseBeanMainMethod() { this.getDeclaringType() instanceof EnterpriseBean and - isMainMethod(this) and + this instanceof MainMethod and not isTestMethod(this) } } diff --git a/java/ql/src/experimental/Security/CWE/CWE-489/StrutsBad.xml b/java/ql/src/experimental/Security/CWE/CWE-489/StrutsBad.xml new file mode 100644 index 00000000000..64e614cc525 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-489/StrutsBad.xml @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/java/ql/src/experimental/Security/CWE/CWE-489/StrutsGood.xml b/java/ql/src/experimental/Security/CWE/CWE-489/StrutsGood.xml new file mode 100644 index 00000000000..369b42a7ec9 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-489/StrutsGood.xml @@ -0,0 +1,11 @@ + + + + + + + + + \ No newline at end of file diff --git a/java/ql/src/experimental/Security/CWE/CWE-489/MainLib.qll b/java/ql/src/experimental/Security/CWE/CWE-489/TestLib.qll similarity index 68% rename from java/ql/src/experimental/Security/CWE/CWE-489/MainLib.qll rename to java/ql/src/experimental/Security/CWE/CWE-489/TestLib.qll index 835aff0b36f..e50f6c97f33 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-489/MainLib.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-489/TestLib.qll @@ -1,17 +1,7 @@ -/** Definitions related to the main method in a test program. */ +/** Definitions related to test methods. */ import java -/** Holds if `m` is the main method of a Java class with the signature `public static void main(String[] args)`. */ -predicate isMainMethod(Method m) { - m.hasName("main") and - m.isStatic() and - m.getReturnType() instanceof VoidType and - m.isPublic() and - m.getNumberOfParameters() = 1 and - m.getParameter(0).getType() instanceof Array -} - /** * Holds if `m` is a test method indicated by: * a) in a test directory such as `src/test/java` diff --git a/java/ql/src/experimental/Security/CWE/CWE-489/WebComponentMain.ql b/java/ql/src/experimental/Security/CWE/CWE-489/WebComponentMain.ql index c3858b30b34..bb96c726147 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-489/WebComponentMain.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-489/WebComponentMain.ql @@ -9,7 +9,7 @@ import java import semmle.code.java.frameworks.Servlets -import MainLib +import TestLib /** The java type `javax.servlet.Filter`. */ class ServletFilterClass extends Class { @@ -48,7 +48,7 @@ class WebComponentMainMethod extends Method { .getASupertype+() .hasQualifiedName("org.springframework.webflow.execution", "Action") // Spring actions ) and - isMainMethod(this) and + this instanceof MainMethod and not isTestMethod(this) } } diff --git a/java/ql/src/experimental/Security/CWE/CWE-489/devMode.qhelp b/java/ql/src/experimental/Security/CWE/CWE-489/devMode.qhelp new file mode 100644 index 00000000000..4775bd8e0e2 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-489/devMode.qhelp @@ -0,0 +1,32 @@ + + + + +

    Turning Apache Struts' development mode configuration on while deploying applications to production environments can lead to remote code execution.

    + +
    + + +

    An application should disable the development mode at the time of deployment.

    + +
    + + +

    The following example shows a `struts.xml` file with `struts.devmode` enabled.

    + + + +

    This can be easily corrected by setting the value of the `struts.devmode` parameter to false.

    + + + +
    + + +
  • + Apache Struts: + Struts development mode configuration +
  • + +
    +
    diff --git a/java/ql/src/experimental/Security/CWE/CWE-489/devMode.ql b/java/ql/src/experimental/Security/CWE/CWE-489/devMode.ql new file mode 100644 index 00000000000..1bbb1b71ab4 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-489/devMode.ql @@ -0,0 +1,24 @@ +/** + * @name Apache Struts development mode enabled + * @description Enabling struts development mode in production environment + * can lead to remote code execution. + * @kind problem + * @problem.severity error + * @precision high + * @id java/struts-development-mode + * @tags security + * external/cwe/cwe-489 + */ + +import java +import experimental.semmle.code.xml.StrutsXML + +bindingset[path] +predicate isLikelyDemoProject(string path) { path.regexpMatch("(?i).*(demo|test|example).*") } + +from ConstantParameter c +where + c.getNameValue() = "struts.devMode" and + c.getValueValue() = "true" and + not isLikelyDemoProject(c.getFile().getRelativePath()) +select c, "Enabling development mode in production environments is dangerous" diff --git a/java/ql/src/experimental/semmle/code/xml/StrutsXML.qll b/java/ql/src/experimental/semmle/code/xml/StrutsXML.qll new file mode 100644 index 00000000000..06e1dab79af --- /dev/null +++ b/java/ql/src/experimental/semmle/code/xml/StrutsXML.qll @@ -0,0 +1,40 @@ +import java + +/** + * A deployment descriptor file, typically called `struts.xml`. + */ +class StrutsXMLFile extends XMLFile { + StrutsXMLFile() { + count(XMLElement e | e = this.getAChild()) = 1 and + this.getAChild().getName() = "struts" + } +} + +/** + * An XML element in a `StrutsXMLFile`. + */ +class StrutsXMLElement extends XMLElement { + StrutsXMLElement() { this.getFile() instanceof StrutsXMLFile } + + /** + * Gets the value for this element, with leading and trailing whitespace trimmed. + */ + string getValue() { result = allCharactersString().trim() } +} + +/** + * A `` element in a `StrutsXMLFile`. + */ +class ConstantParameter extends StrutsXMLElement { + ConstantParameter() { this.getName() = "constant" } + + /** + * Gets the value of the `name` attribute of this ``. + */ + string getNameValue() { result = getAttributeValue("name") } + + /** + * Gets the value of the `value` attribute of this ``. + */ + string getValueValue() { result = getAttributeValue("value") } +} diff --git a/java/ql/src/semmle/code/java/Type.qll b/java/ql/src/semmle/code/java/Type.qll index 7f48467ad9b..10d9b8b3a31 100755 --- a/java/ql/src/semmle/code/java/Type.qll +++ b/java/ql/src/semmle/code/java/Type.qll @@ -599,6 +599,13 @@ class Class extends RefType, @class { /** Holds if this class is a local class. */ predicate isLocal() { isLocalClass(this, _) } + /** Holds if this class is package protected, that is, neither public nor private nor protected. */ + predicate isPackageProtected() { + not isPrivate() and + not isProtected() and + not isPublic() + } + override RefType getSourceDeclaration() { classes(this, _, _, result) } /** @@ -816,6 +823,13 @@ class Interface extends RefType, @interface { any() } + /** Holds if this interface is package protected, that is, neither public nor private nor protected. */ + predicate isPackageProtected() { + not isPrivate() and + not isProtected() and + not isPublic() + } + override string getAPrimaryQlClass() { result = "Interface" } } diff --git a/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll index 0df58641ad6..86f536f8ed7 100644 --- a/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll @@ -64,6 +64,14 @@ import java private import semmle.code.java.dataflow.DataFlow::DataFlow private import internal.DataFlowPrivate +/** + * A module importing the frameworks that provide external flow data, + * ensuring that they are visible to the taint tracking / data flow library. + */ +private module Frameworks { + private import semmle.code.java.frameworks.ApacheHttp +} + private predicate sourceModelCsv(string row) { row = [ @@ -214,7 +222,7 @@ module CsvValidation { not name.regexpMatch("[a-zA-Z0-9_]*") and msg = "Dubious name \"" + name + "\" in " + pred + " model." or - not signature.regexpMatch("|\\([a-zA-Z0-9_\\.\\$<>,]*\\)") and + not signature.regexpMatch("|\\([a-zA-Z0-9_\\.\\$<>,\\[\\]]*\\)") and msg = "Dubious signature \"" + signature + "\" in " + pred + " model." or not ext.regexpMatch("|Annotated") and diff --git a/java/ql/src/semmle/code/java/dataflow/FlowSteps.qll b/java/ql/src/semmle/code/java/dataflow/FlowSteps.qll index cb219650414..39de26ae014 100644 --- a/java/ql/src/semmle/code/java/dataflow/FlowSteps.qll +++ b/java/ql/src/semmle/code/java/dataflow/FlowSteps.qll @@ -9,7 +9,7 @@ private import semmle.code.java.dataflow.DataFlow * A module importing the frameworks that implement additional flow steps, * ensuring that they are visible to the taint tracking library. */ -module Frameworks { +private module Frameworks { private import semmle.code.java.frameworks.jackson.JacksonSerializability private import semmle.code.java.frameworks.android.Intent private import semmle.code.java.frameworks.android.SQLite @@ -17,6 +17,7 @@ module Frameworks { private import semmle.code.java.frameworks.Protobuf private import semmle.code.java.frameworks.guava.Guava private import semmle.code.java.frameworks.apache.Lang + private import semmle.code.java.frameworks.ApacheHttp } /** diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll index 1d2e9052842..54f41545284 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -415,6 +415,30 @@ private module Cached { store(node1, tc.getContent(), node2, contentType, tc.getContainerType()) } + /** + * Holds if data can flow from `fromNode` to `toNode` because they are the post-update + * nodes of some function output and input respectively, where the output and input + * are aliases. A typical example is a function returning `this`, implementing a fluent + * interface. + */ + cached + predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) { + exists(Node fromPre, Node toPre | + fromPre = fromNode.getPreUpdateNode() and + toPre = toNode.getPreUpdateNode() + | + exists(DataFlowCall c | + // Does the language-specific simpleLocalFlowStep already model flow + // from function input to output? + fromPre = getAnOutNode(c, _) and + toPre.(ArgumentNode).argumentOf(c, _) and + simpleLocalFlowStep(toPre.(ArgumentNode), fromPre) + ) + or + argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre) + ) + } + /** * Holds if the call context `call` either improves virtual dispatch in * `callable` or if it allows us to prune unreachable nodes in `callable`. diff --git a/java/ql/src/semmle/code/java/frameworks/ApacheHttp.qll b/java/ql/src/semmle/code/java/frameworks/ApacheHttp.qll index bf31a707add..2dc1077cb4e 100644 --- a/java/ql/src/semmle/code/java/frameworks/ApacheHttp.qll +++ b/java/ql/src/semmle/code/java/frameworks/ApacheHttp.qll @@ -1,8 +1,10 @@ /** - * Provides classes and predicates related to `org.apache.http.*`. + * Provides classes and predicates related to `org.apache.http.*` and `org.apache.hc.*`. */ import java +private import semmle.code.java.dataflow.FlowSteps +private import semmle.code.java.dataflow.ExternalFlow class ApacheHttpGetParams extends Method { ApacheHttpGetParams() { @@ -39,3 +41,192 @@ class TypeApacheHttpRequestBuilder extends Class { this.hasQualifiedName("org.apache.http.client.methods", "RequestBuilder") } } + +private class ApacheHttpSource extends SourceModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.http.protocol;HttpRequestHandler;true;handle;(HttpRequest,HttpResponse,HttpContext);;Parameter[0];remote", + "org.apache.hc.core5.http.io;HttpRequestHandler;true;handle;(ClassicHttpRequest,ClassicHttpResponse,HttpContext);;Parameter[0];remote", + "org.apache.hc.core5.http.io;HttpServerRequestHandler;true;handle;(ClassicHttpRequest,ResponseTrigger,HttpContext);;Parameter[0];remote" + ] + } +} + +/** + * A call that sets a header of an `HttpResponse`. + */ +class ApacheHttpSetHeader extends Call { + ApacheHttpSetHeader() { + exists(Method m | + this.getCallee().(Method).overrides*(m) and + m.getDeclaringType() + .hasQualifiedName(["org.apache.http", "org.apache.hc.core5.http"], "HttpMessage") and + m.hasName(["addHeader", "setHeader"]) and + m.getNumberOfParameters() = 2 + ) + or + exists(Constructor c | + this.getCallee() = c and + c.getDeclaringType() + .hasQualifiedName(["org.apache.http.message", "org.apache.hc.core5.http.message"], + "BasicHeader") + ) + } + + /** Gets the expression used as the name of this header. */ + Expr getName() { result = this.getArgument(0) } + + /** Gets the expression used as the value of this header. */ + Expr getValue() { result = this.getArgument(1) } +} + +private class ApacheHttpXssSink extends SinkModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.http;HttpResponse;true;setEntity;(HttpEntity);;Argument[0];xss", + "org.apache.http.util;EntityUtils;true;updateEntity;(HttpResponse,HttpEntity);;Argument[1];xss", + "org.apache.hc.core5.http;HttpEntityContainer;true;setEntity;(HttpEntity);;Argument[0];xss" + ] + } +} + +private class ApacheHttpFlowStep extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.http;HttpMessage;true;getAllHeaders;();;Argument[-1];ReturnValue;taint", + "org.apache.http;HttpMessage;true;getFirstHeader;(String);;Argument[-1];ReturnValue;taint", + "org.apache.http;HttpMessage;true;getLastHeader;(String);;Argument[-1];ReturnValue;taint", + "org.apache.http;HttpMessage;true;getHeaders;(String);;Argument[-1];ReturnValue;taint", + "org.apache.http;HttpMessage;true;getParams;();;Argument[-1];ReturnValue;taint", + "org.apache.http;HttpMessage;true;headerIterator;();;Argument[-1];ReturnValue;taint", + "org.apache.http;HttpMessage;true;headerIterator;(String);;Argument[-1];ReturnValue;taint", + "org.apache.http;HttpRequest;true;getRequestLine;();;Argument[-1];ReturnValue;taint", + "org.apache.http;HttpEntityEnclosingRequest;true;getEntity;();;Argument[-1];ReturnValue;taint", + "org.apache.http;Header;true;getElements;();;Argument[-1];ReturnValue;taint", + "org.apache.http;HeaderElement;true;getName;();;Argument[-1];ReturnValue;taint", + "org.apache.http;HeaderElement;true;getValue;();;Argument[-1];ReturnValue;taint", + "org.apache.http;HeaderElement;true;getParameter;(int);;Argument[-1];ReturnValue;taint", + "org.apache.http;HeaderElement;true;getParameterByName;(String);;Argument[-1];ReturnValue;taint", + "org.apache.http;HeaderElement;true;getParameters;();;Argument[-1];ReturnValue;taint", + "org.apache.http;NameValuePair;true;getName;();;Argument[-1];ReturnValue;taint", + "org.apache.http;NameValuePair;true;getValue;();;Argument[-1];ReturnValue;taint", + "org.apache.http;HeaderIterator;true;nextHeader;();;Argument[-1];ReturnValue;taint", + "org.apache.http;HttpEntity;true;getContent;();;Argument[-1];ReturnValue;taint", + "org.apache.http;HttpEntity;true;getContentEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.http;HttpEntity;true;getContentType;();;Argument[-1];ReturnValue;taint", + "org.apache.http;RequestLine;true;getMethod;();;Argument[-1];ReturnValue;taint", + "org.apache.http;RequestLine;true;getUri;();;Argument[-1];ReturnValue;taint", + "org.apache.http.params;HttpParams;true;getParameter;(String);;Argument[-1];ReturnValue;taint", + "org.apache.http.params;HttpParams;true;getDoubleParameter;(String,double);;Argument[-1];ReturnValue;taint", + "org.apache.http.params;HttpParams;true;getIntParameter;(String,int);;Argument[-1];ReturnValue;taint", + "org.apache.http.params;HttpParams;true;getLongParameter;(String,long);;Argument[-1];ReturnValue;taint", + "org.apache.http.params;HttpParams;true;getDoubleParameter;(String,double);;Argument[1];ReturnValue;value", + "org.apache.http.params;HttpParams;true;getIntParameter;(String,int);;Argument[1];ReturnValue;value", + "org.apache.http.params;HttpParams;true;getLongParameter;(String,long);;Argument[1];ReturnValue;value", + "org.apache.hc.core5.http;MessageHeaders;true;getFirstHeader;(String);;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;MessageHeaders;true;getLastHeader;(String);;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;MessageHeaders;true;getHeader;(String);;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;MessageHeaders;true;getHeaders;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;MessageHeaders;true;getHeaders;(String);;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;MessageHeaders;true;headerIterator;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;MessageHeaders;true;headerIterator;(String);;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;HttpRequest;true;getAuthority;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;HttpRequest;true;getMethod;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;HttpRequest;true;getPath;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;HttpRequest;true;getUri;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;HttpRequest;true;getRequestUri;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;HttpEntityContainer;true;getEntity;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;NameValuePair;true;getName;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;NameValuePair;true;getValue;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;HttpEntity;true;getContent;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;HttpEntity;true;getTrailers;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;EntityDetails;true;getContentType;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;EntityDetails;true;getContentEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http;EntityDetails;true;getTrailerNames;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http.message;RequestLine;true;getMethod;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http.message;RequestLine;true;getUri;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http.message;RequestLine;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.http.message;RequestLine;true;RequestLine;(HttpRequest);;Argument[0];ReturnValue;taint", + "org.apache.hc.core5.http.message;RequestLine;true;RequestLine;(String,String,ProtocolVersion);;Argument[1];ReturnValue;taint", + "org.apache.hc.core5.http.message;RequestLine;true;RequestLine;(String,String,ProtocolVersion);;Argument[1];ReturnValue;taint", + "org.apache.hc.core5.function;Supplier;true;get;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.net;URIAuthority;true;getHostName;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.net;URIAuthority;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.http.util;EntityUtils;true;toString;;;Argument[0];ReturnValue;taint", + "org.apache.http.util;EntityUtils;true;toByteArray;(HttpEntity);;Argument[0];ReturnValue;taint", + "org.apache.http.util;EntityUtils;true;getContentCharSet;(HttpEntity);;Argument[0];ReturnValue;taint", + "org.apache.http.util;EntityUtils;true;getContentMimeType;(HttpEntity);;Argument[0];ReturnValue;taint", + "org.apache.hc.core5.http.io.entity;EntityUtils;true;toString;;;Argument[0];ReturnValue;taint", + "org.apache.hc.core5.http.io.entity;EntityUtils;true;toByteArray;;;Argument[0];ReturnValue;taint", + "org.apache.hc.core5.http.io.entity;EntityUtils;true;parse;;;Argument[0];ReturnValue;taint", + "org.apache.http.util;EncodingUtils;true;getAsciiBytes;(String);;Argument[0];ReturnValue;taint", + "org.apache.http.util;EncodingUtils;true;getAsciiString;;;Argument[0];ReturnValue;taint", + "org.apache.http.util;EncodingUtils;true;getBytes;(String,String);;Argument[0];ReturnValue;taint", + "org.apache.http.util;EncodingUtils;true;getString;;;Argument[0];ReturnValue;taint", + "org.apache.http.util;Args;true;containsNoBlanks;(T,String);;Argument[0];ReturnValue;value", + "org.apache.http.util;Args;true;notNull;(T,String);;Argument[0];ReturnValue;value", + "org.apache.http.util;Args;true;notEmpty;(T,String);;Argument[0];ReturnValue;value", + "org.apache.http.util;Args;true;notBlank;(T,String);;Argument[0];ReturnValue;value", + "org.apache.hc.core5.util;Args;true;containsNoBlanks;(T,String);;Argument[0];ReturnValue;value", + "org.apache.hc.core5.util;Args;true;notNull;(T,String);;Argument[0];ReturnValue;value", + "org.apache.hc.core5.util;Args;true;notEmpty;(T,String);;Argument[0];ReturnValue;value", + "org.apache.hc.core5.util;Args;true;notBlank;(T,String);;Argument[0];ReturnValue;value", + "org.apache.hc.core5.http.io.entity;HttpEntities;true;create;;;Argument[0];ReturnValue;taint", + "org.apache.hc.core5.http.io.entity;HttpEntities;true;createGzipped;;;Argument[0];ReturnValue;taint", + "org.apache.hc.core5.http.io.entity;HttpEntities;true;createUrlEncoded;;;Argument[0];ReturnValue;taint", + "org.apache.hc.core5.http.io.entity;HttpEntities;true;gzip;(HttpEntity);;Argument[0];ReturnValue;taint", + "org.apache.hc.core5.http.io.entity;HttpEntities;true;withTrailers;;;Argument[0];ReturnValue;taint", + "org.apache.http.entity;BasicHttpEntity;true;setContent;(InputStream);;Argument[0];Argument[-1];taint", + "org.apache.http.entity;BufferedHttpEntity;true;BufferedHttpEntity;(HttpEntity);;Argument[0];ReturnValue;taint", + "org.apache.http.entity;ByteArrayEntity;true;ByteArrayEntity;;;Argument[0];ReturnValue;taint", + "org.apache.http.entity;HttpEntityWrapper;true;HttpEntityWrapper;(HttpEntity);;Argument[0];ReturnValue;taint", + "org.apache.http.entity;InputStreamEntity;true;InputStreamEntity;;;Argument[0];ReturnValue;taint", + "org.apache.http.entity;StringEntity;true;StringEntity;;;Argument[0];ReturnValue;taint", + "org.apache.hc.core5.http.io.entity;BasicHttpEntity;true;BasicHttpEntity;;;Argument[0];ReturnValue;taint", + "org.apache.hc.core5.http.io.entity;BufferedHttpEntity;true;BufferedHttpEntity;(HttpEntity);;Argument[0];ReturnValue;taint", + "org.apache.hc.core5.http.io.entity;ByteArrayEntity;true;ByteArrayEntity;;;Argument[0];ReturnValue;taint", + "org.apache.hc.core5.http.io.entity;HttpEntityWrapper;true;HttpEntityWrapper;(HttpEntity);;Argument[0];ReturnValue;taint", + "org.apache.hc.core5.http.io.entity;InputStreamEntity;true;InputStreamEntity;;;Argument[0];ReturnValue;taint", + "org.apache.hc.core5.http.io.entity;StringEntity;true;StringEntity;;;Argument[0];ReturnValue;taint", + "org.apache.http.util;ByteArrayBuffer;true;append;(byte[],int,int);;Argument[0];Argument[-1];taint", + "org.apache.http.util;ByteArrayBuffer;true;append;(char[],int,int);;Argument[0];Argument[-1];taint", + "org.apache.http.util;ByteArrayBuffer;true;append;(CharArrayBuffer,int,int);;Argument[0];Argument[-1];taint", + "org.apache.http.util;ByteArrayBuffer;true;buffer;();;Argument[-1];ReturnValue;taint", + "org.apache.http.util;ByteArrayBuffer;true;toByteArray;();;Argument[-1];ReturnValue;taint", + "org.apache.http.util;CharArrayBuffer;true;append;(byte[],int,int);;Argument[0];Argument[-1];taint", + "org.apache.http.util;CharArrayBuffer;true;append;(char[],int,int);;Argument[0];Argument[-1];taint", + "org.apache.http.util;CharArrayBuffer;true;append;(CharArrayBuffer,int,int);;Argument[0];Argument[-1];taint", + "org.apache.http.util;CharArrayBuffer;true;append;(ByteArrayBuffer,int,int);;Argument[0];Argument[-1];taint", + "org.apache.http.util;CharArrayBuffer;true;append;(CharArrayBuffer);;Argument[0];Argument[-1];taint", + "org.apache.http.util;CharArrayBuffer;true;append;(String);;Argument[0];Argument[-1];taint", + "org.apache.http.util;CharArrayBuffer;true;append;(Object);;Argument[0];Argument[-1];taint", + "org.apache.http.util;CharArrayBuffer;true;buffer;();;Argument[-1];ReturnValue;taint", + "org.apache.http.util;CharArrayBuffer;true;toCharArray;();;Argument[-1];ReturnValue;taint", + "org.apache.http.util;CharArrayBuffer;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.http.util;CharArrayBuffer;true;substring;(int,int);;Argument[-1];ReturnValue;taint", + "org.apache.http.util;CharArrayBuffer;true;subSequence;(int,int);;Argument[-1];ReturnValue;taint", + "org.apache.http.util;CharArrayBuffer;true;substringTrimmed;(int,int);;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.util;ByteArrayBuffer;true;append;(byte[],int,int);;Argument[0];Argument[-1];taint", + "org.apache.hc.core5.util;ByteArrayBuffer;true;append;(char[],int,int);;Argument[0];Argument[-1];taint", + "org.apache.hc.core5.util;ByteArrayBuffer;true;append;(CharArrayBuffer,int,int);;Argument[0];Argument[-1];taint", + "org.apache.hc.core5.util;ByteArrayBuffer;true;array;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.util;ByteArrayBuffer;true;toByteArray;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.util;CharArrayBuffer;true;append;(byte[],int,int);;Argument[0];Argument[-1];taint", + "org.apache.hc.core5.util;CharArrayBuffer;true;append;(char[],int,int);;Argument[0];Argument[-1];taint", + "org.apache.hc.core5.util;CharArrayBuffer;true;append;(CharArrayBuffer,int,int);;Argument[0];Argument[-1];taint", + "org.apache.hc.core5.util;CharArrayBuffer;true;append;(ByteArrayBuffer,int,int);;Argument[0];Argument[-1];taint", + "org.apache.hc.core5.util;CharArrayBuffer;true;append;(CharArrayBuffer);;Argument[0];Argument[-1];taint", + "org.apache.hc.core5.util;CharArrayBuffer;true;append;(String);;Argument[0];Argument[-1];taint", + "org.apache.hc.core5.util;CharArrayBuffer;true;append;(Object);;Argument[0];Argument[-1];taint", + "org.apache.hc.core5.util;CharArrayBuffer;true;array;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.util;CharArrayBuffer;true;toCharArray;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.util;CharArrayBuffer;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.util;CharArrayBuffer;true;substring;(int,int);;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.util;CharArrayBuffer;true;subSequence;(int,int);;Argument[-1];ReturnValue;taint", + "org.apache.hc.core5.util;CharArrayBuffer;true;substringTrimmed;(int,int);;Argument[-1];ReturnValue;taint" + ] + } +} diff --git a/java/ql/src/semmle/code/java/frameworks/spring/SpringController.qll b/java/ql/src/semmle/code/java/frameworks/spring/SpringController.qll index 3abf325dfa2..f935a4803a9 100644 --- a/java/ql/src/semmle/code/java/frameworks/spring/SpringController.qll +++ b/java/ql/src/semmle/code/java/frameworks/spring/SpringController.qll @@ -126,6 +126,11 @@ class SpringRequestMappingMethod extends SpringControllerMethod { requestMappingAnnotation.getValue("produces").(CompileTimeConstantExpr).getStringValue() } + /** Gets the "value" @RequestMapping annotation value, if present. */ + string getValue() { + result = requestMappingAnnotation.getValue("value").(CompileTimeConstantExpr).getStringValue() + } + /** Holds if this is considered an `@ResponseBody` method. */ predicate isResponseBody() { getAnAnnotation().getType() instanceof SpringResponseBodyAnnotationType or diff --git a/java/ql/src/semmle/code/java/frameworks/spring/SpringWeb.qll b/java/ql/src/semmle/code/java/frameworks/spring/SpringWeb.qll index 4a71c71295e..dd8e660fd26 100644 --- a/java/ql/src/semmle/code/java/frameworks/spring/SpringWeb.qll +++ b/java/ql/src/semmle/code/java/frameworks/spring/SpringWeb.qll @@ -17,3 +17,23 @@ class SpringNativeWebRequest extends Class { this.hasQualifiedName("org.springframework.web.context.request", "NativeWebRequest") } } + +/** + * A Spring `ModelAndView` class. This is either + * `org.springframework.web.servlet.ModelAndView` or + * `org.springframework.web.portlet.ModelAndView`. + */ +class ModelAndView extends Class { + ModelAndView() { + hasQualifiedName(["org.springframework.web.servlet", "org.springframework.web.portlet"], + "ModelAndView") + } +} + +/** A call to the Spring `ModelAndView.setViewName` method. */ +class SpringModelAndViewSetViewNameCall extends MethodAccess { + SpringModelAndViewSetViewNameCall() { + getMethod().getDeclaringType() instanceof ModelAndView and + getMethod().hasName("setViewName") + } +} diff --git a/java/ql/src/semmle/code/java/security/Encryption.qll b/java/ql/src/semmle/code/java/security/Encryption.qll index ddbaf9cba73..c8292a6a42c 100644 --- a/java/ql/src/semmle/code/java/security/Encryption.qll +++ b/java/ql/src/semmle/code/java/security/Encryption.qll @@ -120,13 +120,16 @@ private string algorithmRegex(string algorithmString) { * Gets the name of an algorithm that is known to be insecure. */ string getAnInsecureAlgorithmName() { - result = "DES" or - result = "RC2" or - result = "RC4" or - result = "RC5" or - result = "ARCFOUR" or // a variant of RC4 - result = "ECB" or // encryption mode ECB like AES/ECB/NoPadding is vulnerable to replay and other attacks - result = "AES/CBC/PKCS[5|7]Padding" // CBC mode of operation with PKCS#5 (or PKCS#7) padding is vulnerable to padding oracle attacks + result = + [ + "DES", "RC2", "RC4", "RC5", + // ARCFOUR is a variant of RC4 + "ARCFOUR", + // Encryption mode ECB like AES/ECB/NoPadding is vulnerable to replay and other attacks + "ECB", + // CBC mode of operation with PKCS#5 or PKCS#7 padding is vulnerable to padding oracle attacks + "AES/CBC/PKCS[57]Padding" + ] } /** @@ -163,14 +166,11 @@ string getInsecureAlgorithmRegex() { * Gets the name of an algorithm that is known to be secure. */ string getASecureAlgorithmName() { - result = "RSA" or - result = "SHA256" or - result = "SHA512" or - result = "CCM" or - result = "GCM" or - result = "AES([^a-zA-Z](?!ECB|CBC/PKCS[5|7]Padding)).*" or - result = "Blowfish" or - result = "ECIES" + result = + [ + "RSA", "SHA256", "SHA512", "CCM", "GCM", "AES([^a-zA-Z](?!ECB|CBC/PKCS[57]Padding)).*", + "Blowfish", "ECIES" + ] } private string rankedSecureAlgorithm(int i) { result = rank[i](getASecureAlgorithmName()) } diff --git a/java/ql/src/semmle/code/java/security/UrlRedirect.qll b/java/ql/src/semmle/code/java/security/UrlRedirect.qll index 3f6609159ac..d2be51d2fae 100644 --- a/java/ql/src/semmle/code/java/security/UrlRedirect.qll +++ b/java/ql/src/semmle/code/java/security/UrlRedirect.qll @@ -3,6 +3,7 @@ import java import semmle.code.java.dataflow.DataFlow import semmle.code.java.frameworks.Servlets +import semmle.code.java.frameworks.ApacheHttp /** A URL redirection sink */ abstract class UrlRedirectSink extends DataFlow::Node { } @@ -24,3 +25,13 @@ private class ServletUrlRedirectSink extends UrlRedirectSink { ) } } + +/** A URL redirection sink from Apache Http components. */ +private class ApacheUrlRedirectSink extends UrlRedirectSink { + ApacheUrlRedirectSink() { + exists(ApacheHttpSetHeader c | + c.getName().(CompileTimeConstantExpr).getStringValue() = "Location" and + this.asExpr() = c.getValue() + ) + } +} diff --git a/java/ql/src/semmle/code/java/security/XSS.qll b/java/ql/src/semmle/code/java/security/XSS.qll index a9141965f9b..f51bc0bbdf5 100644 --- a/java/ql/src/semmle/code/java/security/XSS.qll +++ b/java/ql/src/semmle/code/java/security/XSS.qll @@ -7,6 +7,7 @@ import semmle.code.java.frameworks.spring.SpringController import semmle.code.java.frameworks.spring.SpringHttp import semmle.code.java.dataflow.DataFlow import semmle.code.java.dataflow.TaintTracking2 +import semmle.code.java.dataflow.ExternalFlow /** A sink that represent a method that outputs data without applying contextual output encoding. */ abstract class XssSink extends DataFlow::Node { } @@ -31,6 +32,8 @@ class XssAdditionalTaintStep extends Unit { /** A default sink representing methods susceptible to XSS attacks. */ private class DefaultXssSink extends XssSink { DefaultXssSink() { + sinkNode(this, "xss") + or exists(HttpServletResponseSendErrorMethod m, MethodAccess ma | ma.getMethod() = m and this.asExpr() = ma.getArgument(1) diff --git a/java/ql/test/library-tests/dataflow/fluent-methods/Test.java b/java/ql/test/library-tests/dataflow/fluent-methods/Test.java new file mode 100644 index 00000000000..c9c09e667b4 --- /dev/null +++ b/java/ql/test/library-tests/dataflow/fluent-methods/Test.java @@ -0,0 +1,50 @@ +public class Test { + + private String field; + + public Test fluentNoop() { + return this; + } + + public Test indirectlyFluentNoop() { + return this.fluentNoop(); + } + + public Test fluentSet(String x) { + this.field = x; + return this; + } + + public static Test identity(Test t) { + return t; + } + + public String get() { + return field; + } + + public static String source() { + return "taint"; + } + + public static void sink(String s) {} + + public static void test1() { + Test t = new Test(); + t.fluentNoop().fluentSet(source()).fluentNoop(); + sink(t.get()); // $hasTaintFlow=y + } + + public static void test2() { + Test t = new Test(); + Test.identity(t).fluentNoop().fluentSet(source()).fluentNoop(); + sink(t.get()); // $hasTaintFlow=y + } + + public static void test3() { + Test t = new Test(); + t.indirectlyFluentNoop().fluentSet(source()).fluentNoop(); + sink(t.get()); // $hasTaintFlow=y + } + +} diff --git a/java/ql/test/library-tests/dataflow/fluent-methods/flow.expected b/java/ql/test/library-tests/dataflow/fluent-methods/flow.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/dataflow/fluent-methods/flow.ql b/java/ql/test/library-tests/dataflow/fluent-methods/flow.ql new file mode 100644 index 00000000000..6d9ba50efe9 --- /dev/null +++ b/java/ql/test/library-tests/dataflow/fluent-methods/flow.ql @@ -0,0 +1,30 @@ +import java +import semmle.code.java.dataflow.DataFlow +import TestUtilities.InlineExpectationsTest + +class Conf extends DataFlow::Configuration { + Conf() { this = "qltest:dataflow:fluent-methods" } + + override predicate isSource(DataFlow::Node n) { + n.asExpr().(MethodAccess).getMethod().hasName("source") + } + + override predicate isSink(DataFlow::Node n) { + exists(MethodAccess ma | ma.getMethod().hasName("sink") | n.asExpr() = ma.getAnArgument()) + } +} + +class HasFlowTest extends InlineExpectationsTest { + HasFlowTest() { this = "HasFlowTest" } + + override string getARelevantTag() { result = "hasTaintFlow" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasTaintFlow" and + exists(DataFlow::Node src, DataFlow::Node sink, Conf conf | conf.hasFlow(src, sink) | + sink.getLocation() = location and + element = sink.toString() and + value = "y" + ) + } +} diff --git a/java/ql/test/library-tests/frameworks/apache-http/A.java b/java/ql/test/library-tests/frameworks/apache-http/A.java new file mode 100644 index 00000000000..cb09b291860 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/apache-http/A.java @@ -0,0 +1,65 @@ +import org.apache.http.*; +import org.apache.http.protocol.*; +import org.apache.http.message.BasicHeader; +import org.apache.http.util.*; +import org.apache.http.entity.*; +import java.io.IOException; + +class A { + static Object taint() { return null; } + + static void sink(Object o) { } + + class Test1 implements HttpRequestHandler { + public void handle(HttpRequest req, HttpResponse res, HttpContext ctx) throws IOException { + A.sink(req.getRequestLine()); //$hasTaintFlow=y + A.sink(req.getRequestLine().getUri()); //$hasTaintFlow=y + A.sink(req.getRequestLine().getMethod()); //$hasTaintFlow=y + A.sink(req.getAllHeaders()); //$hasTaintFlow=y + HeaderIterator it = req.headerIterator(); + A.sink(it.next()); //$hasTaintFlow=y + A.sink(it.nextHeader()); //$hasTaintFlow=y + Header h = req.getHeaders("abc")[3]; + A.sink(h.getName()); //$hasTaintFlow=y + A.sink(h.getValue()); //$hasTaintFlow=y + HeaderElement el = h.getElements()[0]; + A.sink(el.getName()); //$hasTaintFlow=y + A.sink(el.getValue()); //$hasTaintFlow=y + A.sink(el.getParameters()); //$hasTaintFlow=y + A.sink(el.getParameterByName("abc").getValue()); //$hasTaintFlow=y + A.sink(el.getParameter(0).getName()); //$hasTaintFlow=y + HttpEntity ent = ((HttpEntityEnclosingRequest)req).getEntity(); + A.sink(ent.getContent()); //$hasTaintFlow=y + A.sink(ent.getContentEncoding()); //$hasTaintFlow=y + A.sink(ent.getContentType()); //$hasTaintFlow=y + A.sink(EntityUtils.toString(ent)); //$hasTaintFlow=y + A.sink(EntityUtils.toByteArray(ent)); //$hasTaintFlow=y + A.sink(EntityUtils.getContentCharSet(ent)); //$hasTaintFlow=y + A.sink(EntityUtils.getContentMimeType(ent)); //$hasTaintFlow=y + res.setEntity(new StringEntity("a")); //$hasTaintFlow=y + EntityUtils.updateEntity(res, new ByteArrayEntity(EntityUtils.toByteArray(ent))); //$hasTaintFlow=y + res.setHeader("Location", req.getRequestLine().getUri()); //$hasTaintFlow=y + res.setHeader(new BasicHeader("Location", req.getRequestLine().getUri())); //$hasTaintFlow=y + } + } + + void test2() { + ByteArrayBuffer bbuf = new ByteArrayBuffer(42); + bbuf.append((byte[]) taint(), 0, 3); + sink(bbuf.buffer()); //$hasTaintFlow=y + sink(bbuf.toByteArray()); //$hasTaintFlow=y + + CharArrayBuffer cbuf = new CharArrayBuffer(42); + cbuf.append(bbuf.toByteArray(), 0, 3); + sink(cbuf.toCharArray()); //$hasTaintFlow=y + sink(cbuf.toString()); //$hasTaintFlow=y + sink(cbuf.subSequence(0, 3)); //$hasTaintFlow=y + sink(cbuf.substring(0, 3)); //$hasTaintFlow=y + sink(cbuf.substringTrimmed(0, 3)); //$hasTaintFlow=y + + sink(Args.notNull(taint(), "x")); //$hasTaintFlow=y + sink(Args.notEmpty((String) taint(), "x")); //$hasTaintFlow=y + sink(Args.notBlank((String) taint(), "x")); //$hasTaintFlow=y + sink(Args.notNull("x", (String) taint())); // Good + } +} \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/apache-http/B.java b/java/ql/test/library-tests/frameworks/apache-http/B.java new file mode 100644 index 00000000000..96e5df3289e --- /dev/null +++ b/java/ql/test/library-tests/frameworks/apache-http/B.java @@ -0,0 +1,76 @@ +import org.apache.hc.core5.http.*; +import org.apache.hc.core5.http.protocol.HttpContext; +import org.apache.hc.core5.http.io.HttpRequestHandler; +import org.apache.hc.core5.http.io.HttpServerRequestHandler; +import org.apache.hc.core5.http.message.*; +import org.apache.hc.core5.http.io.entity.*; +import org.apache.hc.core5.util.*; +import java.io.IOException; + +class B { + static Object taint() { return null; } + + static void sink(Object o) { } + + class Test1 implements HttpRequestHandler { + public void handle(ClassicHttpRequest req, ClassicHttpResponse res, HttpContext ctx) throws IOException, ParseException { + B.sink(req.getAuthority().getHostName()); //$hasTaintFlow=y + B.sink(req.getAuthority().toString()); //$hasTaintFlow=y + B.sink(req.getMethod()); //$hasTaintFlow=y + B.sink(req.getPath()); //$hasTaintFlow=y + B.sink(req.getScheme()); + B.sink(req.getRequestUri()); //$hasTaintFlow=y + RequestLine line = new RequestLine(req); + B.sink(line.getUri()); //$hasTaintFlow=y + B.sink(line.getMethod()); //$hasTaintFlow=y + B.sink(req.getHeaders()); //$hasTaintFlow=y + B.sink(req.headerIterator()); //$hasTaintFlow=y + Header h = req.getHeaders("abc")[3]; + B.sink(h.getName()); //$hasTaintFlow=y + B.sink(h.getValue()); //$hasTaintFlow=y + B.sink(req.getFirstHeader("abc")); //$hasTaintFlow=y + B.sink(req.getLastHeader("abc")); //$hasTaintFlow=y + HttpEntity ent = req.getEntity(); + B.sink(ent.getContent()); //$hasTaintFlow=y + B.sink(ent.getContentEncoding()); //$hasTaintFlow=y + B.sink(ent.getContentType()); //$hasTaintFlow=y + B.sink(ent.getTrailerNames()); //$hasTaintFlow=y + B.sink(ent.getTrailers().get()); //$hasTaintFlow=y + B.sink(EntityUtils.toString(ent)); //$hasTaintFlow=y + B.sink(EntityUtils.toByteArray(ent)); //$hasTaintFlow=y + B.sink(EntityUtils.parse(ent)); //$hasTaintFlow=y + res.setEntity(new StringEntity("a")); //$hasTaintFlow=y + res.setEntity(new ByteArrayEntity(EntityUtils.toByteArray(ent), ContentType.TEXT_HTML)); //$hasTaintFlow=y + res.setEntity(HttpEntities.create("a")); //$hasTaintFlow=y + res.setHeader("Location", req.getRequestUri()); //$hasTaintFlow=y + res.setHeader(new BasicHeader("Location", req.getRequestUri())); //$hasTaintFlow=y + } + } + + void test2() { + ByteArrayBuffer bbuf = new ByteArrayBuffer(42); + bbuf.append((byte[]) taint(), 0, 3); + sink(bbuf.array()); //$hasTaintFlow=y + sink(bbuf.toByteArray()); //$hasTaintFlow=y + sink(bbuf.toString()); + + CharArrayBuffer cbuf = new CharArrayBuffer(42); + cbuf.append(bbuf.toByteArray(), 0, 3); + sink(cbuf.toCharArray()); //$hasTaintFlow=y + sink(cbuf.toString()); //$hasTaintFlow=y + sink(cbuf.subSequence(0, 3)); //$hasTaintFlow=y + sink(cbuf.substring(0, 3)); //$hasTaintFlow=y + sink(cbuf.substringTrimmed(0, 3)); //$hasTaintFlow=y + + sink(Args.notNull(taint(), "x")); //$hasTaintFlow=y + sink(Args.notEmpty((String) taint(), "x")); //$hasTaintFlow=y + sink(Args.notBlank((String) taint(), "x")); //$hasTaintFlow=y + sink(Args.notNull("x", (String) taint())); + } + + class Test3 implements HttpServerRequestHandler { + public void handle(ClassicHttpRequest req, HttpServerRequestHandler.ResponseTrigger restr, HttpContext ctx) throws HttpException, IOException { + B.sink(req.getEntity()); //$hasTaintFlow=y + } + } +} \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/apache-http/flow.expected b/java/ql/test/library-tests/frameworks/apache-http/flow.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/frameworks/apache-http/flow.ql b/java/ql/test/library-tests/frameworks/apache-http/flow.ql new file mode 100644 index 00000000000..46856ee648d --- /dev/null +++ b/java/ql/test/library-tests/frameworks/apache-http/flow.ql @@ -0,0 +1,39 @@ +import java +import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.dataflow.FlowSources +import semmle.code.java.security.XSS +import semmle.code.java.security.UrlRedirect +import TestUtilities.InlineExpectationsTest + +class Conf extends TaintTracking::Configuration { + Conf() { this = "qltest:frameworks:apache-http" } + + override predicate isSource(DataFlow::Node n) { + n.asExpr().(MethodAccess).getMethod().hasName("taint") + or + n instanceof RemoteFlowSource + } + + override predicate isSink(DataFlow::Node n) { + exists(MethodAccess ma | ma.getMethod().hasName("sink") | n.asExpr() = ma.getAnArgument()) + or + n instanceof XssSink + or + n instanceof UrlRedirectSink + } +} + +class HasFlowTest extends InlineExpectationsTest { + HasFlowTest() { this = "HasFlowTest" } + + override string getARelevantTag() { result = "hasTaintFlow" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasTaintFlow" and + exists(DataFlow::Node src, DataFlow::Node sink, Conf conf | conf.hasFlow(src, sink) | + sink.getLocation() = location and + element = sink.toString() and + value = "y" + ) + } +} diff --git a/java/ql/test/library-tests/frameworks/apache-http/options b/java/ql/test/library-tests/frameworks/apache-http/options new file mode 100644 index 00000000000..50ea0f87825 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/apache-http/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/apache-http-4.4.13:${testdir}/../../../stubs/apache-http-5 \ No newline at end of file diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/Header.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/Header.java index b742e110a34..6e4886fc85c 100644 --- a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/Header.java +++ b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/Header.java @@ -1,8 +1,4 @@ /* - * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/Header.java $ - * $Revision: 569636 $ - * $Date: 2007-08-25 00:34:47 -0700 (Sat, 25 Aug 2007) $ - * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -33,38 +29,25 @@ package org.apache.http; /** * Represents an HTTP header field. - * - *

    - * The HTTP header fields follow the same generic format as that given in - * Section 3.1 of RFC 822. Each header field consists of a name followed by a - * colon (":") and the field value. Field names are case-insensitive. The field - * value MAY be preceded by any amount of LWS, though a single SP is preferred. * - *

    + * 

    The HTTP header fields follow the same generic format as + * that given in Section 3.1 of RFC 822. Each header field consists + * of a name followed by a colon (":") and the field value. Field names + * are case-insensitive. The field value MAY be preceded by any amount + * of LWS, though a single SP is preferred. + * + *

      *     message-header = field-name ":" [ field-value ]
      *     field-name     = token
      *     field-value    = *( field-content | LWS )
      *     field-content  = <the OCTETs making up the field-value
      *                      and consisting of either *TEXT or combinations
      *                      of token, separators, and quoted-string>
    - * 
    - * - * @author Remy Maucherat - * @author Oleg Kalnichevski - * @version $Revision: 569636 $ + *
    * - * @deprecated Please use {@link java.net.URL#openConnection} instead. Please - * visit this - * webpage for further details. + * @since 4.0 */ -@Deprecated -public interface Header { - - String getName(); - - String getValue(); - +public interface Header extends NameValuePair { HeaderElement[] getElements() throws ParseException; } diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/HttpResponse.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/HttpResponse.java new file mode 100644 index 00000000000..5dbfd6d7875 --- /dev/null +++ b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/HttpResponse.java @@ -0,0 +1,55 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http; + +import java.util.Locale; + +public interface HttpResponse extends HttpMessage { + // StatusLine getStatusLine(); + + // void setStatusLine(StatusLine statusline); + + // void setStatusLine(ProtocolVersion ver, int code); + + // void setStatusLine(ProtocolVersion ver, int code, String reason); + + void setStatusCode(int code) + throws IllegalStateException; + + void setReasonPhrase(String reason) + throws IllegalStateException; + + HttpEntity getEntity(); + + void setEntity(HttpEntity entity); + + Locale getLocale(); + + void setLocale(Locale loc); + +} diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/entity/AbstractHttpEntity.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/entity/AbstractHttpEntity.java new file mode 100644 index 00000000000..455882abfe7 --- /dev/null +++ b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/entity/AbstractHttpEntity.java @@ -0,0 +1,74 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.entity; + +import java.io.IOException; +import org.apache.http.HttpEntity; +import org.apache.http.Header; + +public abstract class AbstractHttpEntity implements HttpEntity { + @Override + public Header getContentType() { + return null; + } + + @Override + public Header getContentEncoding() { + return null; + } + + @Override + public boolean isChunked() { + return false; + } + + public void setContentType(final Header contentType) { + } + + public void setContentType(final String ctString) { + } + + public void setContentEncoding(final Header contentEncoding) { + } + + public void setContentEncoding(final String ceString) { + } + + public void setChunked(final boolean b) { + } + + @Override + public void consumeContent() throws IOException { + } + + @Override + public String toString() { + return null; + } + +} diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/entity/ByteArrayEntity.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/entity/ByteArrayEntity.java new file mode 100644 index 00000000000..44c946fc2f6 --- /dev/null +++ b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/entity/ByteArrayEntity.java @@ -0,0 +1,78 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.entity; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + + +public class ByteArrayEntity extends AbstractHttpEntity implements Cloneable { + public ByteArrayEntity(final byte[] b, final ContentType contentType) { + } + + public ByteArrayEntity(final byte[] b, final int off, final int len, final ContentType contentType) { + } + + public ByteArrayEntity(final byte[] b) { + } + + public ByteArrayEntity(final byte[] b, final int off, final int len) { + } + + @Override + public boolean isRepeatable() { + return false; + } + + @Override + public long getContentLength() { + return 0; + } + + @Override + public InputStream getContent() { + return null; + } + + @Override + public void writeTo(final OutputStream outStream) throws IOException { + } + + @Override + public boolean isStreaming() { + return false; + } + + @Override + public Object clone() throws CloneNotSupportedException { + return null; + } + +} diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/entity/ContentType.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/entity/ContentType.java new file mode 100644 index 00000000000..6f4554e4d59 --- /dev/null +++ b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/entity/ContentType.java @@ -0,0 +1,35 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.entity; + +import java.io.Serializable; + + +public final class ContentType implements Serializable { + +} diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/entity/StringEntity.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/entity/StringEntity.java new file mode 100644 index 00000000000..3c4d8515e24 --- /dev/null +++ b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/entity/StringEntity.java @@ -0,0 +1,87 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.entity; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; + + +public class StringEntity extends AbstractHttpEntity implements Cloneable { + public StringEntity(final String string, final ContentType contentType) throws UnsupportedCharsetException { + } + + public StringEntity( + final String string, final String mimeType, final String charset) throws UnsupportedEncodingException { + } + + public StringEntity(final String string, final String charset) + throws UnsupportedCharsetException { + } + + public StringEntity(final String string, final Charset charset) { + } + + public StringEntity(final String string) + throws UnsupportedEncodingException { + } + + @Override + public boolean isRepeatable() { + return false; + } + + @Override + public long getContentLength() { + return 0; + } + + @Override + public InputStream getContent() throws IOException { + return null; + } + + @Override + public void writeTo(final OutputStream outStream) throws IOException { + } + + @Override + public boolean isStreaming() { + return false; + } + + @Override + public Object clone() throws CloneNotSupportedException { + return null; + } + +} diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/message/BasicHeader.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/message/BasicHeader.java new file mode 100644 index 00000000000..052c3abc0f8 --- /dev/null +++ b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/message/BasicHeader.java @@ -0,0 +1,65 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.message; + +import java.io.Serializable; + +import org.apache.http.Header; +import org.apache.http.HeaderElement; +import org.apache.http.ParseException; + +public class BasicHeader implements Header, Cloneable, Serializable { + public BasicHeader(final String name, final String value) { + } + + @Override + public Object clone() throws CloneNotSupportedException { + return null; + } + + @Override + public HeaderElement[] getElements() throws ParseException { + return null; + } + + @Override + public String getName() { + return null; + } + + @Override + public String getValue() { + return null; + } + + @Override + public String toString() { + return null; + } + +} diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/protocol/HttpContext.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/protocol/HttpContext.java new file mode 100644 index 00000000000..4c0ad5b9cd8 --- /dev/null +++ b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/protocol/HttpContext.java @@ -0,0 +1,37 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.protocol; + +public interface HttpContext { + Object getAttribute(String id); + + void setAttribute(String id, Object obj); + + Object removeAttribute(String id); + +} diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/protocol/HttpRequestHandler.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/protocol/HttpRequestHandler.java new file mode 100644 index 00000000000..e7fee4ca031 --- /dev/null +++ b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/protocol/HttpRequestHandler.java @@ -0,0 +1,38 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.protocol; + +import java.io.IOException; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; + +public interface HttpRequestHandler { + void handle(HttpRequest request, HttpResponse response, HttpContext context) + throws IOException; + +} diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/util/Args.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/util/Args.java new file mode 100644 index 00000000000..60b314d1ca0 --- /dev/null +++ b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/util/Args.java @@ -0,0 +1,78 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.util; + +import java.util.Collection; + +public class Args { + public static void check(final boolean expression, final String message) { + } + + public static void check(final boolean expression, final String message, final Object... args) { + } + + public static void check(final boolean expression, final String message, final Object arg) { + } + + public static T notNull(final T argument, final String name) { + return null; + } + + public static T notEmpty(final T argument, final String name) { + return null; + } + + public static T notBlank(final T argument, final String name) { + return null; + } + + public static T containsNoBlanks(final T argument, final String name) { + return null; + } + + public static > T notEmpty(final T argument, final String name) { + return null; + } + + public static int positive(final int n, final String name) { + return 0; + } + + public static long positive(final long n, final String name) { + return 0; + } + + public static int notNegative(final int n, final String name) { + return 0; + } + + public static long notNegative(final long n, final String name) { + return 0; + } + +} diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/util/ByteArrayBuffer.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/util/ByteArrayBuffer.java new file mode 100644 index 00000000000..9bc34144de1 --- /dev/null +++ b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/util/ByteArrayBuffer.java @@ -0,0 +1,93 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.util; + +import java.io.Serializable; + +public final class ByteArrayBuffer implements Serializable { + public ByteArrayBuffer(final int capacity) { + } + + public void append(final byte[] b, final int off, final int len) { + } + + public void append(final int b) { + } + + public void append(final char[] b, final int off, final int len) { + } + + public void append(final CharArrayBuffer b, final int off, final int len) { + } + + public void clear() { + } + + public byte[] toByteArray() { + return null; + } + + public int byteAt(final int i) { + return 0; + } + + public int capacity() { + return 0; + } + + public int length() { + return 0; + } + + public void ensureCapacity(final int required) { + } + + public byte[] buffer() { + return null; + } + + public void setLength(final int len) { + } + + public boolean isEmpty() { + return false; + } + + public boolean isFull() { + return false; + } + + public int indexOf(final byte b, final int from, final int to) { + return 0; + } + + public int indexOf(final byte b) { + return 0; + } + +} diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/util/ByteBuffer.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/util/ByteBuffer.java new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/util/CharArrayBuffer.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/util/CharArrayBuffer.java new file mode 100644 index 00000000000..465962e362e --- /dev/null +++ b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/util/CharArrayBuffer.java @@ -0,0 +1,127 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.util; + +import java.io.Serializable; +import java.nio.CharBuffer; + + +public final class CharArrayBuffer implements CharSequence, Serializable { + public CharArrayBuffer(final int capacity) { + } + + public void append(final char[] b, final int off, final int len) { + } + + public void append(final String str) { + } + + public void append(final CharArrayBuffer b, final int off, final int len) { + } + + public void append(final CharArrayBuffer b) { + } + + public void append(final char ch) { + } + + public void append(final byte[] b, final int off, final int len) { + } + + public void append(final ByteArrayBuffer b, final int off, final int len) { + } + + public void append(final Object obj) { + } + + public void clear() { + } + + public char[] toCharArray() { + return null; + } + + @Override + public char charAt(final int i) { + return 0; + } + + public char[] buffer() { + return null; + } + + public int capacity() { + return 0; + } + + @Override + public int length() { + return 0; + } + + public void ensureCapacity(final int required) { + } + + public void setLength(final int len) { + } + + public boolean isEmpty() { + return false; + } + + public boolean isFull() { + return false; + } + + public int indexOf(final int ch, final int from, final int to) { + return 0; + } + + public int indexOf(final int ch) { + return 0; + } + + public String substring(final int beginIndex, final int endIndex) { + return null; + } + + public String substringTrimmed(final int beginIndex, final int endIndex) { + return null; + } + + @Override + public CharSequence subSequence(final int beginIndex, final int endIndex) { + return null; + } + + @Override + public String toString() { + return null; + } + +} diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/util/EntityUtils.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/util/EntityUtils.java new file mode 100644 index 00000000000..1af8795c3f3 --- /dev/null +++ b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/util/EntityUtils.java @@ -0,0 +1,72 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.util; + +import java.io.IOException; +import java.nio.charset.Charset; +import org.apache.http.*; + + +public final class EntityUtils { + public static void consumeQuietly(final HttpEntity entity) { + } + + public static void consume(final HttpEntity entity) throws IOException { + } + + public static void updateEntity( + final HttpResponse response, final HttpEntity entity) throws IOException { + } + + public static byte[] toByteArray(final HttpEntity entity) throws IOException { + return null; + } + + public static String getContentCharSet(final HttpEntity entity) { + return null; + } + + public static String getContentMimeType(final HttpEntity entity) { + return null; + } + + public static String toString( + final HttpEntity entity, final Charset defaultCharset) throws IOException { + return null; + } + + public static String toString( + final HttpEntity entity, final String defaultCharset) throws IOException { + return null; + } + + public static String toString(final HttpEntity entity) throws IOException, ParseException { + return null; + } + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/function/Supplier.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/function/Supplier.java new file mode 100644 index 00000000000..c847728f32f --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/function/Supplier.java @@ -0,0 +1,33 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.function; + +public interface Supplier { + T get(); + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/ClassicHttpRequest.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/ClassicHttpRequest.java new file mode 100644 index 00000000000..9997a4f0cb1 --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/ClassicHttpRequest.java @@ -0,0 +1,36 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http; + +/** + * 'Classic' {@link HttpRequest} message that can enclose {@link HttpEntity}. + * + * @since 5.0 + */ +public interface ClassicHttpRequest extends HttpRequest, HttpEntityContainer { +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/ClassicHttpResponse.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/ClassicHttpResponse.java new file mode 100644 index 00000000000..571f1b0c420 --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/ClassicHttpResponse.java @@ -0,0 +1,33 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http; + +import java.io.Closeable; + +public interface ClassicHttpResponse extends HttpResponse, HttpEntityContainer, Closeable { +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/ContentType.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/ContentType.java new file mode 100644 index 00000000000..f7d3ffc21a3 --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/ContentType.java @@ -0,0 +1,159 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http; +import java.io.Serializable; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.charset.UnsupportedCharsetException; + +public final class ContentType implements Serializable { + public static final ContentType APPLICATION_ATOM_XML = null; + + public static final ContentType APPLICATION_FORM_URLENCODED = null; + + public static final ContentType APPLICATION_JSON = null; + + public static final ContentType APPLICATION_NDJSON = null; + + public static final ContentType APPLICATION_OCTET_STREAM = null; + + public static final ContentType APPLICATION_PDF = null; + + public static final ContentType APPLICATION_SOAP_XML = null; + + public static final ContentType APPLICATION_SVG_XML = null; + + public static final ContentType APPLICATION_XHTML_XML = null; + + public static final ContentType APPLICATION_XML = null; + + public static final ContentType APPLICATION_PROBLEM_JSON = null; + + public static final ContentType APPLICATION_PROBLEM_XML = null; + + public static final ContentType APPLICATION_RSS_XML = null; + + public static final ContentType IMAGE_BMP = null; + + public static final ContentType IMAGE_GIF = null; + + public static final ContentType IMAGE_JPEG = null; + + public static final ContentType IMAGE_PNG = null; + + public static final ContentType IMAGE_SVG = null; + + public static final ContentType IMAGE_TIFF = null; + + public static final ContentType IMAGE_WEBP = null; + + public static final ContentType MULTIPART_FORM_DATA = null; + + public static final ContentType MULTIPART_MIXED = null; + + public static final ContentType MULTIPART_RELATED = null; + + public static final ContentType TEXT_HTML = null; + + public static final ContentType TEXT_MARKDOWN = null; + + public static final ContentType TEXT_PLAIN = null; + + public static final ContentType TEXT_XML = null; + + public static final ContentType TEXT_EVENT_STREAM = null; + + public static final ContentType WILDCARD = null; + + private static final NameValuePair[] EMPTY_NAME_VALUE_PAIR_ARRAY = new NameValuePair[0]; + + public String getMimeType() { + return null; + } + + public Charset getCharset() { + return null; + } + + public String getParameter(final String name) { + return null; + } + + @Override + public String toString() { + return null; + } + + public static ContentType create(final String mimeType, final Charset charset) { + return null; + } + + public static ContentType create(final String mimeType) { + return null; + } + + public static ContentType create( + final String mimeType, final String charset) throws UnsupportedCharsetException { + return null; + } + + public static ContentType create( + final String mimeType, final NameValuePair... params) throws UnsupportedCharsetException { + return null; + } + + public static ContentType parse(final CharSequence s) throws UnsupportedCharsetException { + return null; + } + + public static ContentType parseLenient(final CharSequence s) throws UnsupportedCharsetException { + return null; + } + + public static ContentType getByMimeType(final String mimeType) { + return null; + } + + public ContentType withCharset(final Charset charset) { + return null; + } + + public ContentType withCharset(final String charset) { + return null; + } + + public ContentType withParameters( + final NameValuePair... params) throws UnsupportedCharsetException { + return null; + } + + public boolean isSameMimeType(final ContentType contentType) { + return false; + } + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/EntityDetails.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/EntityDetails.java new file mode 100644 index 00000000000..bed26e033f7 --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/EntityDetails.java @@ -0,0 +1,43 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http; + +import java.util.Set; + +public interface EntityDetails { + long getContentLength(); + + String getContentType(); + + String getContentEncoding(); + + boolean isChunked(); + + Set getTrailerNames(); + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/Header.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/Header.java new file mode 100644 index 00000000000..888e80e1748 --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/Header.java @@ -0,0 +1,39 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http; + +/** + * Represents an HTTP header field consisting of a field name and a field + * value. + * + * @since 4.0 + */ +public interface Header extends NameValuePair { + boolean isSensitive(); + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/HttpEntity.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/HttpEntity.java new file mode 100644 index 00000000000..02f47cd4e41 --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/HttpEntity.java @@ -0,0 +1,48 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http; + +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.List; + +import org.apache.hc.core5.function.Supplier; + +public interface HttpEntity extends EntityDetails, Closeable { + boolean isRepeatable(); + + InputStream getContent() throws IOException, UnsupportedOperationException; + + void writeTo(OutputStream outStream) throws IOException; + + boolean isStreaming(); + Supplier> getTrailers(); + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/HttpEntityContainer.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/HttpEntityContainer.java new file mode 100644 index 00000000000..dbde2e9966c --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/HttpEntityContainer.java @@ -0,0 +1,40 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http; + +/** + * Contains an {@link HttpEntity}. + * + * @since 5.0 + */ +public interface HttpEntityContainer { + HttpEntity getEntity(); + + void setEntity(HttpEntity entity); + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/HttpException.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/HttpException.java new file mode 100644 index 00000000000..a5943cf543f --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/HttpException.java @@ -0,0 +1,48 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http; + +/** + * Signals that an HTTP exception has occurred. + * + * @since 4.0 + */ +public class HttpException extends Exception { + public HttpException() { + } + + public HttpException(final String message) { + } + + public HttpException(final String format, final Object... args) { + } + + public HttpException(final String message, final Throwable cause) { + } + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/HttpMessage.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/HttpMessage.java new file mode 100644 index 00000000000..425e3a2719c --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/HttpMessage.java @@ -0,0 +1,55 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http; + +/** + * HTTP messages consist of requests from client to server and responses + * from server to client. + * + * @since 4.0 + */ +public interface HttpMessage extends MessageHeaders { + void setVersion(ProtocolVersion version); + + ProtocolVersion getVersion(); + + void addHeader(Header header); + + void addHeader(String name, Object value); + + void setHeader(Header header); + + void setHeader(String name, Object value); + + void setHeaders(Header... headers); + + boolean removeHeader(Header header); + + boolean removeHeaders(String name); + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/HttpRequest.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/HttpRequest.java new file mode 100644 index 00000000000..e16c157b030 --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/HttpRequest.java @@ -0,0 +1,56 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.hc.core5.net.URIAuthority; + +public interface HttpRequest extends HttpMessage { + String getMethod(); + + String getPath(); + + void setPath(String path); + + String getScheme(); + + void setScheme(String scheme); + + URIAuthority getAuthority(); + + void setAuthority(URIAuthority authority); + + String getRequestUri(); + + URI getUri() throws URISyntaxException; + + void setUri(final URI requestUri); + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/HttpResponse.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/HttpResponse.java new file mode 100644 index 00000000000..4a962d484ff --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/HttpResponse.java @@ -0,0 +1,45 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http; + +import java.util.Locale; + +public interface HttpResponse extends HttpMessage { + int getCode(); + + void setCode(int code); + + String getReasonPhrase(); + + void setReasonPhrase(String reason); + + Locale getLocale(); + + void setLocale(Locale loc); + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/MessageHeaders.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/MessageHeaders.java new file mode 100644 index 00000000000..374910f5f2b --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/MessageHeaders.java @@ -0,0 +1,51 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http; + +import java.util.Iterator; + +public interface MessageHeaders { + boolean containsHeader(String name); + + int countHeaders(String name); + + Header getFirstHeader(String name); + + Header getHeader(String name) throws ProtocolException; + + Header[] getHeaders(); + + Header[] getHeaders(String name); + + Header getLastHeader(String name); + + Iterator
    headerIterator(); + + Iterator
    headerIterator(String name); + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/NameValuePair.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/NameValuePair.java new file mode 100644 index 00000000000..b7e793994db --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/NameValuePair.java @@ -0,0 +1,40 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http; + +/** + * A name-value pair parameter used as an element of HTTP messages. + * + * @since 4.0 + */ +public interface NameValuePair { + String getName(); + + String getValue(); + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/ParseException.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/ParseException.java new file mode 100644 index 00000000000..c0c180c7a8c --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/ParseException.java @@ -0,0 +1,52 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http; + +/** + * Signals a protocol exception due to failure to parse a message element. + * + * @since 4.0 + */ +public class ParseException extends ProtocolException { + public ParseException() { + } + + public ParseException(final String message) { + } + + public ParseException(final String description, final CharSequence text, final int off, final int len, final int errorOffset) { + } + + public ParseException(final String description, final CharSequence text, final int off, final int len) { + } + + public int getErrorOffset() { + return 0; + } + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/ProtocolException.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/ProtocolException.java new file mode 100644 index 00000000000..fee74e55bba --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/ProtocolException.java @@ -0,0 +1,49 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http; + +/** + * Signals that an HTTP protocol violation has occurred. + * For example a malformed status line or headers, a missing message body, etc. + * + * @since 4.0 + */ +public class ProtocolException extends HttpException { + public ProtocolException() { + } + + public ProtocolException(final String message) { + } + + public ProtocolException(final String format, final Object... args) { + } + + public ProtocolException(final String message, final Throwable cause) { + } + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/ProtocolVersion.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/ProtocolVersion.java new file mode 100644 index 00000000000..37f17cf8b8d --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/ProtocolVersion.java @@ -0,0 +1,87 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http; + +import java.io.Serializable; + +public class ProtocolVersion implements Serializable { + public ProtocolVersion(final String protocol, final int major, final int minor) { + } + + public final String getProtocol() { + return null; + } + + public final int getMajor() { + return 0; + } + + public final int getMinor() { + return 0; + } + + @Override + public final int hashCode() { + return 0; + } + + public final boolean equals(final int major, final int minor) { + return false; + } + + @Override + public final boolean equals(final Object obj) { + return false; + } + + public String format() { + return null; + } + + public boolean isComparable(final ProtocolVersion that) { + return false; + } + + public int compareToVersion(final ProtocolVersion that) { + return 0; + } + + public final boolean greaterEquals(final ProtocolVersion version) { + return false; + } + + public final boolean lessEquals(final ProtocolVersion version) { + return false; + } + + @Override + public String toString() { + return null; + } + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/HttpRequestHandler.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/HttpRequestHandler.java new file mode 100644 index 00000000000..13197bc3de4 --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/HttpRequestHandler.java @@ -0,0 +1,41 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http.io; + +import java.io.IOException; + +import org.apache.hc.core5.http.ClassicHttpRequest; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpException; +import org.apache.hc.core5.http.protocol.HttpContext; + +public interface HttpRequestHandler { + void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) + throws HttpException, IOException; + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/HttpServerRequestHandler.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/HttpServerRequestHandler.java new file mode 100644 index 00000000000..007bf18568d --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/HttpServerRequestHandler.java @@ -0,0 +1,46 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.hc.core5.http.io; +import java.io.IOException; +import org.apache.hc.core5.http.ClassicHttpRequest; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpException; +import org.apache.hc.core5.http.protocol.HttpContext; + +public interface HttpServerRequestHandler { + interface ResponseTrigger { + void sendInformation(ClassicHttpResponse response) throws HttpException, IOException; + + void submitResponse(ClassicHttpResponse response) throws HttpException, IOException; + + } + void handle( + ClassicHttpRequest request, + ResponseTrigger responseTrigger, + HttpContext context) throws HttpException, IOException; + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/entity/AbstractHttpEntity.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/entity/AbstractHttpEntity.java new file mode 100644 index 00000000000..68af8819fe0 --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/entity/AbstractHttpEntity.java @@ -0,0 +1,86 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http.io.entity; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.apache.hc.core5.function.Supplier; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.util.Args; + +public abstract class AbstractHttpEntity implements HttpEntity { + public static void writeTo(final HttpEntity entity, final OutputStream outStream) throws IOException { + } + + @Override + public void writeTo(final OutputStream outStream) throws IOException { + } + + @Override + public final String getContentType() { + return null; + } + + @Override + public final String getContentEncoding() { + return null; + } + + @Override + public final boolean isChunked() { + return false; + } + + @Override + public boolean isRepeatable() { + return false; + } + + @Override + public Supplier> getTrailers() { + return null; + } + + @Override + public Set getTrailerNames() { + return null; + } + + @Override + public String toString() { + return null; + } + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/entity/ByteArrayEntity.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/entity/ByteArrayEntity.java new file mode 100644 index 00000000000..d0f9b715050 --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/entity/ByteArrayEntity.java @@ -0,0 +1,92 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http.io.entity; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import org.apache.hc.core5.http.ContentType; + +public class ByteArrayEntity extends AbstractHttpEntity { + public ByteArrayEntity( + final byte[] b, final int off, final int len, final ContentType contentType, final String contentEncoding, + final boolean chunked) { + } + + public ByteArrayEntity( + final byte[] b, final int off, final int len, final ContentType contentType, final String contentEncoding) { + } + + public ByteArrayEntity( + final byte[] b, final ContentType contentType, final String contentEncoding, final boolean chunked) { + } + + public ByteArrayEntity(final byte[] b, final ContentType contentType, final String contentEncoding) { + } + + public ByteArrayEntity(final byte[] b, final ContentType contentType, final boolean chunked) { + } + + public ByteArrayEntity(final byte[] b, final ContentType contentType) { + } + + public ByteArrayEntity( + final byte[] b, final int off, final int len, final ContentType contentType, final boolean chunked) { + } + + public ByteArrayEntity(final byte[] b, final int off, final int len, final ContentType contentType) { + } + + @Override + public final boolean isRepeatable() { + return false; + } + + @Override + public final long getContentLength() { + return 0; + } + + @Override + public final InputStream getContent() { + return null; + } + + @Override + public final void writeTo(final OutputStream outStream) throws IOException { + } + + @Override + public final boolean isStreaming() { + return false; + } + + @Override + public final void close() throws IOException { + } + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/entity/ByteBufferEntity.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/entity/ByteBufferEntity.java new file mode 100644 index 00000000000..555ccd69fe5 --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/entity/ByteBufferEntity.java @@ -0,0 +1,65 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http.io.entity; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import org.apache.hc.core5.http.ContentType; + +public class ByteBufferEntity extends AbstractHttpEntity { + public ByteBufferEntity(final ByteBuffer buffer, final ContentType contentType, final String contentEncoding) { + } + + public ByteBufferEntity(final ByteBuffer buffer, final ContentType contentType) { + } + + @Override + public final boolean isRepeatable() { + return false; + } + + @Override + public final long getContentLength() { + return 0; + } + + @Override + public final InputStream getContent() throws IOException, UnsupportedOperationException { + return null; + } + + @Override + public final boolean isStreaming() { + return false; + } + + @Override + public final void close() throws IOException { + } + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/entity/EntityUtils.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/entity/EntityUtils.java new file mode 100644 index 00000000000..cbf7bfda9bb --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/entity/EntityUtils.java @@ -0,0 +1,89 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http.io.entity; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.List; + +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.NameValuePair; +import org.apache.hc.core5.http.ParseException; + +public final class EntityUtils { + public static void consumeQuietly(final HttpEntity entity) { + } + + public static void consume(final HttpEntity entity) throws IOException { + } + + public static byte[] toByteArray(final HttpEntity entity) throws IOException { + return null; + } + + public static byte[] toByteArray(final HttpEntity entity, final int maxResultLength) throws IOException { + return null; + } + + public static String toString( + final HttpEntity entity, final Charset defaultCharset) throws IOException, ParseException { + return null; + } + + public static String toString( + final HttpEntity entity, final Charset defaultCharset, final int maxResultLength) throws IOException, ParseException { + return null; + } + + public static String toString( + final HttpEntity entity, final String defaultCharset) throws IOException, ParseException { + return null; + } + + public static String toString( + final HttpEntity entity, final String defaultCharset, final int maxResultLength) throws IOException, ParseException { + return null; + } + + public static String toString(final HttpEntity entity) throws IOException, ParseException { + return null; + } + + public static String toString(final HttpEntity entity, final int maxResultLength) throws IOException, ParseException { + return null; + } + + public static List parse(final HttpEntity entity) throws IOException { + return null; + } + + public static List parse(final HttpEntity entity, final int maxStreamLength) throws IOException { + return null; + } + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/entity/HttpEntities.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/entity/HttpEntities.java new file mode 100644 index 00000000000..d7e532439f4 --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/entity/HttpEntities.java @@ -0,0 +1,152 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http.io.entity; +import java.io.File; +import java.io.OutputStream; +import java.io.Serializable; +import java.nio.charset.Charset; +import java.nio.file.Path; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.NameValuePair; +import org.apache.hc.core5.io.IOCallback; + +public final class HttpEntities { + public static HttpEntity create(final String content, final ContentType contentType) { + return null; + } + + public static HttpEntity create(final String content, final Charset charset) { + return null; + } + + public static HttpEntity create(final String content) { + return null; + } + + public static HttpEntity create(final byte[] content, final ContentType contentType) { + return null; + } + + public static HttpEntity create(final File content, final ContentType contentType) { + return null; + } + + public static HttpEntity create(final Serializable serializable, final ContentType contentType) { + return null; + } + + public static HttpEntity createUrlEncoded( + final Iterable parameters, final Charset charset) { + return null; + } + + public static HttpEntity create(final IOCallback callback, final ContentType contentType) { + return null; + } + + public static HttpEntity gzip(final HttpEntity entity) { + return null; + } + + public static HttpEntity createGzipped(final String content, final ContentType contentType) { + return null; + } + + public static HttpEntity createGzipped(final String content, final Charset charset) { + return null; + } + + public static HttpEntity createGzipped(final String content) { + return null; + } + + public static HttpEntity createGzipped(final byte[] content, final ContentType contentType) { + return null; + } + + public static HttpEntity createGzipped(final File content, final ContentType contentType) { + return null; + } + + public static HttpEntity createGzipped(final Serializable serializable, final ContentType contentType) { + return null; + } + + public static HttpEntity createGzipped(final IOCallback callback, final ContentType contentType) { + return null; + } + + public static HttpEntity createGzipped(final Path content, final ContentType contentType) { + return null; + } + + public static HttpEntity withTrailers(final HttpEntity entity, final Header... trailers) { + return null; + } + + public static HttpEntity create(final String content, final ContentType contentType, final Header... trailers) { + return null; + } + + public static HttpEntity create(final String content, final Charset charset, final Header... trailers) { + return null; + } + + public static HttpEntity create(final String content, final Header... trailers) { + return null; + } + + public static HttpEntity create(final byte[] content, final ContentType contentType, final Header... trailers) { + return null; + } + + public static HttpEntity create(final File content, final ContentType contentType, final Header... trailers) { + return null; + } + + public static HttpEntity create( + final Serializable serializable, final ContentType contentType, final Header... trailers) { + return null; + } + + public static HttpEntity create( + final IOCallback callback, final ContentType contentType, final Header... trailers) { + return null; + } + + public static HttpEntity create(final Path content, final ContentType contentType) { + return null; + } + + public static HttpEntity create(final Path content, final ContentType contentType, final Header... trailers) { + return null; + } + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/entity/StringEntity.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/entity/StringEntity.java new file mode 100644 index 00000000000..649ce534350 --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/io/entity/StringEntity.java @@ -0,0 +1,83 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http.io.entity; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.Charset; +import org.apache.hc.core5.http.ContentType; + +public class StringEntity extends AbstractHttpEntity { + public StringEntity( + final String string, final ContentType contentType, final String contentEncoding, final boolean chunked) { + } + + public StringEntity(final String string, final ContentType contentType, final boolean chunked) { + } + + public StringEntity(final String string, final ContentType contentType) { + } + + public StringEntity(final String string, final Charset charset) { + } + + public StringEntity(final String string, final Charset charset, final boolean chunked) { + } + + public StringEntity(final String string) { + } + + @Override + public final boolean isRepeatable() { + return false; + } + + @Override + public final long getContentLength() { + return 0; + } + + @Override + public final InputStream getContent() throws IOException { + return null; + } + + @Override + public final void writeTo(final OutputStream outStream) throws IOException { + } + + @Override + public final boolean isStreaming() { + return false; + } + + @Override + public final void close() throws IOException { + } + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/message/BasicHeader.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/message/BasicHeader.java new file mode 100644 index 00000000000..64a2d3d8668 --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/message/BasicHeader.java @@ -0,0 +1,59 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http.message; +import java.io.Serializable; +import org.apache.hc.core5.http.Header; + +public class BasicHeader implements Header, Cloneable, Serializable { + public BasicHeader(final String name, final Object value) { + } + + public BasicHeader(final String name, final Object value, final boolean sensitive) { + } + + @Override + public String getName() { + return null; + } + + @Override + public String getValue() { + return null; + } + + @Override + public boolean isSensitive() { + return false; + } + + @Override + public String toString() { + return null; + } + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/message/RequestLine.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/message/RequestLine.java new file mode 100644 index 00000000000..86f1aaab695 --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/message/RequestLine.java @@ -0,0 +1,61 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http.message; + +import java.io.Serializable; + +import org.apache.hc.core5.http.HttpRequest; +import org.apache.hc.core5.http.ProtocolVersion; + +public final class RequestLine implements Serializable { + public RequestLine(final HttpRequest request) { + } + + public RequestLine(final String method, + final String uri, + final ProtocolVersion version) { + } + + public String getMethod() { + return null; + } + + public ProtocolVersion getProtocolVersion() { + return null; + } + + public String getUri() { + return null; + } + + @Override + public String toString() { + return null; + } + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/protocol/HttpContext.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/protocol/HttpContext.java new file mode 100644 index 00000000000..1506409dc25 --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/http/protocol/HttpContext.java @@ -0,0 +1,42 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.http.protocol; +import org.apache.hc.core5.http.ProtocolVersion; + +public interface HttpContext { + ProtocolVersion getProtocolVersion(); + + void setProtocolVersion(ProtocolVersion version); + + Object getAttribute(String id); + + Object setAttribute(String id, Object obj); + + Object removeAttribute(String id); + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/io/IOCallback.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/io/IOCallback.java new file mode 100644 index 00000000000..9e1f7f9c7ac --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/io/IOCallback.java @@ -0,0 +1,34 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.io; +import java.io.IOException; + +public interface IOCallback { + void execute(T object) throws IOException; + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/net/URIAuthority.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/net/URIAuthority.java new file mode 100644 index 00000000000..3bb5158370a --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/net/URIAuthority.java @@ -0,0 +1,55 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.net; + +public final class URIAuthority { + public String getUserInfo() { + return null; + } + + public String getHostName() { + return null; + } + + public int getPort() { + return 0; + } + + public String toString() { + return null; + } + + public boolean equals(final Object obj) { + return false; + } + + public int hashCode() { + return 0; + } + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/util/Args.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/util/Args.java new file mode 100644 index 00000000000..3e1a70bfca3 --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/util/Args.java @@ -0,0 +1,93 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.util; + +import org.apache.hc.core5.http.EntityDetails; + +import java.util.Collection; + +public class Args { + public static void check(final boolean expression, final String message) { + } + + public static void check(final boolean expression, final String message, final Object... args) { + } + + public static void check(final boolean expression, final String message, final Object arg) { + } + + public static long checkContentLength(final EntityDetails entityDetails) { + return 0; + } + + public static int checkRange(final int value, final int lowInclusive, final int highInclusive, + final String message) { + return 0; + } + + public static long checkRange(final long value, final long lowInclusive, final long highInclusive, + final String message) { + return 0; + } + + public static T containsNoBlanks(final T argument, final String name) { + return null; + } + + public static T notBlank(final T argument, final String name) { + return null; + } + + public static T notEmpty(final T argument, final String name) { + return null; + } + + public static > T notEmpty(final T argument, final String name) { + return null; + } + + public static int notNegative(final int n, final String name) { + return 0; + } + + public static long notNegative(final long n, final String name) { + return 0; + } + + public static T notNull(final T argument, final String name) { + return null; + } + + public static int positive(final int n, final String name) { + return 0; + } + + public static long positive(final long n, final String name) { + return 0; + } +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/util/ByteArrayBuffer.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/util/ByteArrayBuffer.java new file mode 100644 index 00000000000..43f131d9405 --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/util/ByteArrayBuffer.java @@ -0,0 +1,97 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.util; + +import java.io.Serializable; +import java.nio.ByteBuffer; + +public final class ByteArrayBuffer implements Serializable { + public ByteArrayBuffer(final int capacity) { + } + + public void append(final byte[] b, final int off, final int len) { + } + + public void append(final int b) { + } + + public void append(final char[] b, final int off, final int len) { + } + + public void append(final CharArrayBuffer b, final int off, final int len) { + } + + public void append(final ByteBuffer buffer) { + } + + public void clear() { + } + + public byte[] toByteArray() { + return null; + } + + public int byteAt(final int i) { + return 0; + } + + public int capacity() { + return 0; + } + + public int length() { + return 0; + } + + public void ensureCapacity(final int required) { + } + + public byte[] array() { + return null; + } + + public void setLength(final int len) { + } + + public boolean isEmpty() { + return false; + } + + public boolean isFull() { + return false; + } + + public int indexOf(final byte b, final int from, final int to) { + return 0; + } + + public int indexOf(final byte b) { + return 0; + } + +} diff --git a/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/util/CharArrayBuffer.java b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/util/CharArrayBuffer.java new file mode 100644 index 00000000000..41b51b2113d --- /dev/null +++ b/java/ql/test/stubs/apache-http-5/org/apache/hc/core5/util/CharArrayBuffer.java @@ -0,0 +1,125 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.core5.util; + +import java.io.Serializable; + +public final class CharArrayBuffer implements CharSequence, Serializable { + public CharArrayBuffer(final int capacity) { + } + + public void append(final char[] b, final int off, final int len) { + } + + public void append(final String str) { + } + + public void append(final CharArrayBuffer b, final int off, final int len) { + } + + public void append(final CharArrayBuffer b) { + } + + public void append(final char ch) { + } + + public void append(final byte[] b, final int off, final int len) { + } + + public void append(final ByteArrayBuffer b, final int off, final int len) { + } + + public void append(final Object obj) { + } + + public void clear() { + } + + public char[] toCharArray() { + return null; + } + + @Override + public char charAt(final int i) { + return 0; + } + + public char[] array() { + return null; + } + + public int capacity() { + return 0; + } + + @Override + public int length() { + return 0; + } + + public void ensureCapacity(final int required) { + } + + public void setLength(final int len) { + } + + public boolean isEmpty() { + return false; + } + + public boolean isFull() { + return false; + } + + public int indexOf(final int ch, final int from, final int to) { + return 0; + } + + public int indexOf(final int ch) { + return 0; + } + + public String substring(final int beginIndex, final int endIndex) { + return null; + } + + public String substringTrimmed(final int beginIndex, final int endIndex) { + return null; + } + + @Override + public CharSequence subSequence(final int beginIndex, final int endIndex) { + return null; + } + + @Override + public String toString() { + return null; + } + +} diff --git a/javascript/change-notes/2021-02-18-typescript-4.2.md b/javascript/change-notes/2021-02-18-typescript-4.2.md new file mode 100644 index 00000000000..6641d259f23 --- /dev/null +++ b/javascript/change-notes/2021-02-18-typescript-4.2.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* TypeScript 4.2 is now supported. diff --git a/javascript/change-notes/2021-02-25-http-proxy.md b/javascript/change-notes/2021-02-25-http-proxy.md new file mode 100644 index 00000000000..5c34368ffcb --- /dev/null +++ b/javascript/change-notes/2021-02-25-http-proxy.md @@ -0,0 +1,4 @@ +lgtm,codescanning +* Sources of user input and sinks for `js/request-forgery` in the http-proxy are now recognized. + Affected packages are + [http-proxy](https://www.npmjs.com/package/http-proxy) \ No newline at end of file diff --git a/javascript/change-notes/2021-02-26-form-data.md b/javascript/change-notes/2021-02-26-form-data.md new file mode 100644 index 00000000000..00ad017fad1 --- /dev/null +++ b/javascript/change-notes/2021-02-26-form-data.md @@ -0,0 +1,4 @@ +lgtm,codescanning +* URIs used in the form-data library are now recognized as sinks for `js/request-forgery`. + Affected packages are + [form-data](https://www.npmjs.com/package/form-data) \ No newline at end of file diff --git a/javascript/change-notes/2021-03-01-ajv.md b/javascript/change-notes/2021-03-01-ajv.md new file mode 100644 index 00000000000..c06bd4f5807 --- /dev/null +++ b/javascript/change-notes/2021-03-01-ajv.md @@ -0,0 +1,8 @@ +lgtm,codescanning +* The security queries now recognize the effect of JSON schema validation, and highlights + cases where this validation is susceptible to denial-of-service attacks. + Affects the package [ajv](https://npmjs.com/package/ajv). +* A new query, `js/resource-exhaustion-from-deep-object-traversal`, has been added to the query suite, + highlighting denial-of-service attacks exploiting operations that traverse deeply user-controlled objects. +* The `js/xss-through-exception` query now recognizes JSON schema validation errors as a source, as they + may contain part of the input data. diff --git a/javascript/extractor/lib/typescript/package.json b/javascript/extractor/lib/typescript/package.json index 0f6fc082bb4..cb3119c7ab2 100644 --- a/javascript/extractor/lib/typescript/package.json +++ b/javascript/extractor/lib/typescript/package.json @@ -2,7 +2,7 @@ "name": "typescript-parser-wrapper", "private": true, "dependencies": { - "typescript": "4.1.2" + "typescript": "4.2.2" }, "scripts": { "build": "tsc --project tsconfig.json", diff --git a/javascript/extractor/lib/typescript/src/type_table.ts b/javascript/extractor/lib/typescript/src/type_table.ts index b750d5a0d85..7b64cad09c4 100644 --- a/javascript/extractor/lib/typescript/src/type_table.ts +++ b/javascript/extractor/lib/typescript/src/type_table.ts @@ -632,7 +632,14 @@ export class TypeTable { ? tupleType.minLength : this.typeChecker.getTypeArguments(tupleReference).length; let hasRestElement = tupleType.hasRestElement ? 't' : 'f'; - let prefix = `tuple;${minLength};${hasRestElement}`; + let restIndex = -1; + for (let i = 0; i < tupleType.elementFlags.length; i++) { + if (tupleType.elementFlags[i] & ts.ElementFlags.Rest) { + restIndex = i; + break; + } + } + let prefix = `tuple;${minLength};${restIndex}`; return this.makeTypeStringVectorFromTypeReferenceArguments(prefix, type); } if (objectFlags & ts.ObjectFlags.Anonymous) { @@ -940,6 +947,9 @@ export class TypeTable { * Returns a unique string for the given call/constructor signature. */ private getSignatureString(kind: ts.SignatureKind, signature: AugmentedSignature): string { + let modifiers : ts.ModifiersArray = signature.getDeclaration()?.modifiers; + let isAbstract = modifiers && modifiers.filter(modifier => modifier.kind == ts.SyntaxKind.AbstractKeyword).length > 0 + let parameters = signature.getParameters(); let numberOfTypeParameters = signature.typeParameters == null ? 0 @@ -971,7 +981,7 @@ export class TypeTable { if (returnTypeId == null) { return null; } - let tag = `${kind};${numberOfTypeParameters};${requiredParameters};${restParameterTag};${returnTypeId}`; + let tag = `${kind};${isAbstract ? "t" : "f"};${numberOfTypeParameters};${requiredParameters};${restParameterTag};${returnTypeId}`; for (let typeParameter of signature.typeParameters || []) { tag += ";" + typeParameter.symbol.name; let constraint = typeParameter.getConstraint(); diff --git a/javascript/extractor/lib/typescript/yarn.lock b/javascript/extractor/lib/typescript/yarn.lock index be708347dab..84f20b2c51c 100644 --- a/javascript/extractor/lib/typescript/yarn.lock +++ b/javascript/extractor/lib/typescript/yarn.lock @@ -6,7 +6,7 @@ version "12.7.11" resolved node-12.7.11.tgz#be879b52031cfb5d295b047f5462d8ef1a716446 -typescript@4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.2.tgz#6369ef22516fe5e10304aae5a5c4862db55380e9" - integrity sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ== +typescript@4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.2.tgz#1450f020618f872db0ea17317d16d8da8ddb8c4c" + integrity sha512-tbb+NVrLfnsJy3M59lsDgrzWIflR4d4TIUjz+heUnHZwdF7YsrMTKoRERiIvI2lvBG95dfpLxB21WZhys1bgaQ== diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java index b9fb9237556..2e80bd4d4a9 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/Main.java +++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java @@ -43,7 +43,7 @@ public class Main { * A version identifier that should be updated every time the extractor changes in such a way that * it may produce different tuples for the same file under the same {@link ExtractorConfig}. */ - public static final String EXTRACTOR_VERSION = "2021-02-05"; + public static final String EXTRACTOR_VERSION = "2021-02-24"; public static final Pattern NEWLINE = Pattern.compile("\n"); diff --git a/javascript/extractor/src/com/semmle/ts/extractor/TypeExtractor.java b/javascript/extractor/src/com/semmle/ts/extractor/TypeExtractor.java index 08f261b71de..de0b2558c4d 100644 --- a/javascript/extractor/src/com/semmle/ts/extractor/TypeExtractor.java +++ b/javascript/extractor/src/com/semmle/ts/extractor/TypeExtractor.java @@ -118,10 +118,11 @@ public class TypeExtractor { } case tupleKind: { - // The first two parts denote minimum length and presence of rest element. + // The first two parts denote minimum length and index of rest element (or -1 if no rest element). trapWriter.addTuple("tuple_type_min_length", lbl, Integer.parseInt(parts[1])); - if (parts[2].equals("t")) { - trapWriter.addTuple("tuple_type_rest", lbl); + int restIndex = Integer.parseInt(parts[2]); + if (restIndex != -1) { + trapWriter.addTuple("tuple_type_rest_index", lbl, restIndex); } firstChild += 2; break; @@ -201,18 +202,22 @@ public class TypeExtractor { private void extractSignature(int index) { // Format is: - // kind;numTypeParams;requiredParams;restParamType;returnType(;paramName;paramType)* + // kind;isAbstract;numTypeParams;requiredParams;restParamType;returnType(;paramName;paramType)* String[] parts = split(table.getSignatureString(index)); Label label = trapWriter.globalID("signature;" + index); int kind = Integer.parseInt(parts[0]); - int numberOfTypeParameters = Integer.parseInt(parts[1]); - int requiredParameters = Integer.parseInt(parts[2]); - String restParamTypeTag = parts[3]; + boolean isAbstract = parts[1].equals("t"); + if (isAbstract) { + trapWriter.addTuple("is_abstract_signature", label); + } + int numberOfTypeParameters = Integer.parseInt(parts[2]); + int requiredParameters = Integer.parseInt(parts[3]); + String restParamTypeTag = parts[4]; if (!restParamTypeTag.isEmpty()) { trapWriter.addTuple( "signature_rest_parameter", label, trapWriter.globalID("type;" + restParamTypeTag)); } - Label returnType = trapWriter.globalID("type;" + parts[4]); + Label returnType = trapWriter.globalID("type;" + parts[5]); trapWriter.addTuple( "signature_types", label, @@ -221,9 +226,9 @@ public class TypeExtractor { numberOfTypeParameters, requiredParameters); trapWriter.addTuple("signature_contains_type", returnType, label, -1); - int numberOfParameters = (parts.length - 5) / 2; // includes type parameters + int numberOfParameters = (parts.length - 6) / 2; // includes type parameters for (int i = 0; i < numberOfParameters; ++i) { - int partIndex = 5 + (2 * i); + int partIndex = 6 + (2 * i); String paramName = parts[partIndex]; String paramTypeId = parts[partIndex + 1]; if (paramTypeId.length() > 0) { // Unconstrained type parameters have an empty type ID. diff --git a/javascript/ql/src/Security/CWE-079/ExceptionXss.qhelp b/javascript/ql/src/Security/CWE-079/ExceptionXss.qhelp index f815794f6b8..7ab1038b067 100644 --- a/javascript/ql/src/Security/CWE-079/ExceptionXss.qhelp +++ b/javascript/ql/src/Security/CWE-079/ExceptionXss.qhelp @@ -5,8 +5,8 @@

    -Directly writing exceptions to a webpage without sanitization allows for a cross-site scripting -vulnerability if the value of the exception can be influenced by a user. +Directly writing error messages to a webpage without sanitization allows for a cross-site scripting +vulnerability if parts of the error message can be influenced by a user.

    @@ -27,6 +27,19 @@ leaving the website vulnerable to cross-site scripting. + +

    +This second example shows an input being validated using the JSON schema validator ajv, +and in case of an error, the error message is sent directly back in the response. +

    + +

    +This is unsafe, because the error message can contain parts of the input. +For example, the input {'<img src=x onerror=alert(1)>': 'foo'} will generate the error +data/<img src=x onerror=alert(1)> should be number, causing reflected XSS. +

    +
    +
  • OWASP: diff --git a/javascript/ql/src/Security/CWE-079/ExceptionXss.ql b/javascript/ql/src/Security/CWE-079/ExceptionXss.ql index 0926894fb7e..7c9cedc1705 100644 --- a/javascript/ql/src/Security/CWE-079/ExceptionXss.ql +++ b/javascript/ql/src/Security/CWE-079/ExceptionXss.ql @@ -19,4 +19,4 @@ from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) select sink.getNode(), source, sink, "$@ is reinterpreted as HTML without escaping meta-characters.", source.getNode(), - "Exception text" + source.getNode().(Source).getDescription() diff --git a/javascript/ql/src/Security/CWE-079/examples/ExceptionXssAjv.js b/javascript/ql/src/Security/CWE-079/examples/ExceptionXssAjv.js new file mode 100644 index 00000000000..8a3ddedb249 --- /dev/null +++ b/javascript/ql/src/Security/CWE-079/examples/ExceptionXssAjv.js @@ -0,0 +1,13 @@ +import express from 'express'; +import Ajv from 'ajv'; + +let app = express(); +let ajv = new Ajv(); + +ajv.addSchema({type: 'object', additionalProperties: {type: 'number'}}, 'pollData'); + +app.post('/polldata', (req, res) => { + if (!ajv.validate('pollData', req.body)) { + res.send(ajv.errorsText()); + } +}); diff --git a/javascript/ql/src/Security/CWE-400/DeepObjectResourceExhaustion.qhelp b/javascript/ql/src/Security/CWE-400/DeepObjectResourceExhaustion.qhelp new file mode 100644 index 00000000000..e778d9237d5 --- /dev/null +++ b/javascript/ql/src/Security/CWE-400/DeepObjectResourceExhaustion.qhelp @@ -0,0 +1,55 @@ + + + + +

    + Processing user-controlled data with a method that allocates excessive amounts + of memory can lead to denial of service. +

    + +

    + If the JSON schema validation library ajv is configured with + allErrors: true there is no limit to how many error objects + will be allocated. An attacker can exploit this by sending an object that + deliberately contains a huge number of errors, and in some cases, with + longer and longer error messages. This can cause the service to become + unresponsive due to the slow error-checking process. +

    +
    + + +

    + Do not use allErrors: true in production. +

    +
    + + +

    + In the example below, the user-submitted object req.body is + validated using ajv and allErrors: true: +

    + + + +

    + Although this ensures that req.body conforms to the schema, + the validation itself could be vulnerable to a denial-of-service attack. + An attacker could send an object containing so many errors that the server + runs out of memory. +

    + +

    + A solution is to not pass in allErrors: true, which means + ajv will only report the first error, not all of them: +

    + + +
    + + +
  • Ajv documentation: security considerations +
  • +
    + diff --git a/javascript/ql/src/Security/CWE-400/DeepObjectResourceExhaustion.ql b/javascript/ql/src/Security/CWE-400/DeepObjectResourceExhaustion.ql new file mode 100644 index 00000000000..69ce56fd17f --- /dev/null +++ b/javascript/ql/src/Security/CWE-400/DeepObjectResourceExhaustion.ql @@ -0,0 +1,23 @@ +/** + * @name Resources exhaustion from deep object traversal + * @description Processing user-controlled object hierarchies inefficiently can lead to denial of service. + * @kind path-problem + * @problem.severity warning + * @precision high + * @id js/resource-exhaustion-from-deep-object-traversal + * @tags security + * external/cwe/cwe-400 + */ + +import javascript +import DataFlow::PathGraph +import semmle.javascript.security.dataflow.DeepObjectResourceExhaustion::DeepObjectResourceExhaustion + +from + Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node link, + string reason +where + cfg.hasFlowPath(source, sink) and + sink.getNode().(Sink).hasReason(link, reason) +select sink, source, sink, "Denial of service caused by processing user input from $@ with $@.", + source.getNode(), "here", link, reason diff --git a/javascript/ql/src/Security/CWE-400/examples/DeepObjectResourceExhaustion.js b/javascript/ql/src/Security/CWE-400/examples/DeepObjectResourceExhaustion.js new file mode 100644 index 00000000000..dfeac169558 --- /dev/null +++ b/javascript/ql/src/Security/CWE-400/examples/DeepObjectResourceExhaustion.js @@ -0,0 +1,14 @@ +import express from 'express'; +import Ajv from 'ajv'; + +let ajv = new Ajv({ allErrors: true }); +ajv.addSchema(require('./input-schema'), 'input'); + +var app = express(); +app.get('/user/:id', function(req, res) { + if (!ajv.validate('input', req.body)) { + res.end(ajv.errorsText()); + return; + } + // ... +}); diff --git a/javascript/ql/src/Security/CWE-400/examples/DeepObjectResourceExhaustion_fixed.js b/javascript/ql/src/Security/CWE-400/examples/DeepObjectResourceExhaustion_fixed.js new file mode 100644 index 00000000000..0c16bf565b2 --- /dev/null +++ b/javascript/ql/src/Security/CWE-400/examples/DeepObjectResourceExhaustion_fixed.js @@ -0,0 +1,14 @@ +import express from 'express'; +import Ajv from 'ajv'; + +let ajv = new Ajv({ allErrors: process.env['REST_DEBUG'] }); +ajv.addSchema(require('./input-schema'), 'input'); + +var app = express(); +app.get('/user/:id', function(req, res) { + if (!ajv.validate('input', req.body)) { + res.end(ajv.errorsText()); + return; + } + // ... +}); diff --git a/javascript/ql/src/javascript.qll b/javascript/ql/src/javascript.qll index d83f173071c..62d1c3f0eb0 100644 --- a/javascript/ql/src/javascript.qll +++ b/javascript/ql/src/javascript.qll @@ -36,6 +36,7 @@ import semmle.javascript.InclusionTests import semmle.javascript.JSDoc import semmle.javascript.JSON import semmle.javascript.JsonParsers +import semmle.javascript.JsonSchema import semmle.javascript.JsonStringifiers import semmle.javascript.JSX import semmle.javascript.Lines @@ -94,6 +95,7 @@ import semmle.javascript.frameworks.LazyCache import semmle.javascript.frameworks.LodashUnderscore import semmle.javascript.frameworks.Logging import semmle.javascript.frameworks.HttpFrameworks +import semmle.javascript.frameworks.HttpProxy import semmle.javascript.frameworks.Markdown import semmle.javascript.frameworks.NoSQL import semmle.javascript.frameworks.PkgCloud diff --git a/javascript/ql/src/semmle/javascript/AMD.qll b/javascript/ql/src/semmle/javascript/AMD.qll index 74ba3d204af..2b89a49a8cb 100644 --- a/javascript/ql/src/semmle/javascript/AMD.qll +++ b/javascript/ql/src/semmle/javascript/AMD.qll @@ -158,7 +158,7 @@ class AmdModuleDefinition extends CallExpr { result = [getAnImplicitExportsValue(), getAnExplicitExportsValue()] } - pragma[noinline] + pragma[noinline, nomagic] private AbstractValue getAnImplicitExportsValue() { // implicit exports: anything that is returned from the factory function result = getModuleExpr().analyze().getAValue() diff --git a/javascript/ql/src/semmle/javascript/Arrays.qll b/javascript/ql/src/semmle/javascript/Arrays.qll index 47b3771560b..0114dd923a8 100644 --- a/javascript/ql/src/semmle/javascript/Arrays.qll +++ b/javascript/ql/src/semmle/javascript/Arrays.qll @@ -25,7 +25,7 @@ module ArrayTaintTracking { // `array.map(function (elt, i, ary) { ... })`: if `array` is tainted, then so are // `elt` and `ary`; similar for `forEach` exists(Function f | - call.getArgument(0).analyze().getAValue().(AbstractFunction).getFunction() = f and + call.getArgument(0).getAFunctionValue(0).getFunction() = f and call.(DataFlow::MethodCallNode).getMethodName() = ["map", "forEach"] and pred = call.getReceiver() and succ = DataFlow::parameterNode(f.getParameter([0, 2])) diff --git a/javascript/ql/src/semmle/javascript/DOM.qll b/javascript/ql/src/semmle/javascript/DOM.qll index 5b1b9c30542..bc61174695c 100644 --- a/javascript/ql/src/semmle/javascript/DOM.qll +++ b/javascript/ql/src/semmle/javascript/DOM.qll @@ -344,7 +344,7 @@ module DOM { or exists(JQuery::MethodCall call | this = call and call.getMethodName() = "get" | call.getNumArgument() = 1 and - forex(InferredType t | t = call.getArgument(0).analyze().getAType() | t = TTNumber()) + unique(InferredType t | t = call.getArgument(0).analyze().getAType()) = TTNumber() ) or // A `this` node from a callback given to a `$().each(callback)` call. diff --git a/javascript/ql/src/semmle/javascript/Expr.qll b/javascript/ql/src/semmle/javascript/Expr.qll index a03bb54e6f6..37576ec643f 100644 --- a/javascript/ql/src/semmle/javascript/Expr.qll +++ b/javascript/ql/src/semmle/javascript/Expr.qll @@ -115,7 +115,7 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode { predicate isImpure() { any() } /** - * Holds if this expression is pure, that is, is its evaluation is guaranteed + * Holds if this expression is pure, that is, its evaluation is guaranteed * to be side-effect free. */ predicate isPure() { not isImpure() } diff --git a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll index 0e1e3a41065..207d6f3010a 100644 --- a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll @@ -415,7 +415,7 @@ module AccessPath { pragma[inline] DataFlow::SourceNode getAnAliasedSourceNode(DataFlow::Node node) { exists(DataFlow::SourceNode root, string accessPath | - node = AccessPath::getAReferenceTo(root, accessPath) and + node = pragma[only_bind_into](AccessPath::getAReferenceTo(root, accessPath)) and result = AccessPath::getAReferenceTo(root, accessPath) ) or diff --git a/javascript/ql/src/semmle/javascript/JsonSchema.qll b/javascript/ql/src/semmle/javascript/JsonSchema.qll new file mode 100644 index 00000000000..5c3306bf64b --- /dev/null +++ b/javascript/ql/src/semmle/javascript/JsonSchema.qll @@ -0,0 +1,129 @@ +/** + * Provides classes and predicates for working with JSON schema libraries. + */ + +import javascript + +/** + * Provides classes and predicates for working with JSON schema libraries. + */ +module JsonSchema { + /** A call that validates an input against a JSON schema. */ + abstract class ValidationCall extends DataFlow::CallNode { + /** Gets the data flow node whose value is being validated. */ + abstract DataFlow::Node getInput(); + + /** Gets the return value that indicates successful validation. */ + boolean getPolarity() { result = true } + } + + /** A data flow node that is used a JSON schema. */ + abstract class SchemaRoot extends DataFlow::Node { } + + /** An object literal with a `$schema` property indicating it is the root of a JSON schema. */ + private class SchemaNodeByTag extends SchemaRoot, DataFlow::ObjectLiteralNode { + SchemaNodeByTag() { + getAPropertyWrite("$schema").getRhs().getStringValue().matches("%//json-schema.org%") + } + } + + /** Gets a data flow node that is part of a JSON schema. */ + private DataFlow::SourceNode getAPartOfJsonSchema(DataFlow::TypeBackTracker t) { + t.start() and + result = any(SchemaRoot n).getALocalSource() + or + result = getAPartOfJsonSchema(t.continue()).getAPropertySource() + or + exists(DataFlow::TypeBackTracker t2 | result = getAPartOfJsonSchema(t2).backtrack(t2, t)) + } + + /** Gets a data flow node that is part of a JSON schema. */ + DataFlow::SourceNode getAPartOfJsonSchema() { + result = getAPartOfJsonSchema(DataFlow::TypeBackTracker::end()) + } + + /** Provides a model of the `ajv` library. */ + module Ajv { + /** A method on `Ajv` that returns `this`. */ + private string chainedMethod() { + result = + ["addSchema", "addMetaSchema", "removeSchema", "addFormat", "addKeyword", "removeKeyword"] + } + + /** An instance of `ajv`. */ + class Instance extends API::InvokeNode { + Instance() { this = API::moduleImport("ajv").getAnInstantiation() } + + /** Gets the data flow node holding the options passed to this `Ajv` instance. */ + DataFlow::Node getOptionsArg() { result = getArgument(0) } + + /** Gets an API node that refers to this object. */ + API::Node ref() { + result = getReturn() + or + result = ref().getMember(chainedMethod()).getReturn() + } + + /** + * Gets an API node for a function produced by `new Ajv().compile()` or similar. + * + * Note that this does not include the instance method `new Ajv().validate` as its + * signature is different. + */ + API::Node getAValidationFunction() { + result = ref().getMember(["compile", "getSchema"]).getReturn() + or + result = ref().getMember("compileAsync").getPromised() + } + + /** + * Gets an API node that refers to an error produced by this Ajv instance. + */ + API::Node getAValidationError() { + exists(API::Node base | base = [ref(), getAValidationFunction()] | + result = base.getMember("errors") + or + result = base.getMember("errorsText").getReturn() + ) + } + } + + /** A call to the `validate` method of `ajv`. */ + class AjvValidationCall extends ValidationCall { + Instance instance; + int argIndex; + + AjvValidationCall() { + this = instance.ref().getMember("validate").getACall() and argIndex = 1 + or + this = instance.getAValidationFunction().getACall() and argIndex = 0 + } + + override DataFlow::Node getInput() { result = getArgument(argIndex) } + + /** Gets the argument holding additional options to the call. */ + DataFlow::Node getOwnOptionsArg() { result = getArgument(argIndex + 1) } + + /** Gets a data flow passed as the extra options to this validation call or to the underlying `Ajv` instance. */ + DataFlow::Node getAnOptionsArg() { + result = getOwnOptionsArg() + or + result = instance.getOptionsArg() + } + + /** Gets the ajv instance doing the validation. */ + Instance getAjvInstance() { result = instance } + } + + private class AjvSchemaNode extends SchemaRoot { + AjvSchemaNode() { + this = + any(Instance i) + .ref() + .getMember(["addSchema", "validate", "compile", "compileAsync"]) + .getParameter(0) + .getARhs() + } + } + } +} diff --git a/javascript/ql/src/semmle/javascript/MembershipCandidates.qll b/javascript/ql/src/semmle/javascript/MembershipCandidates.qll index 568651c3f1a..89573252ab5 100644 --- a/javascript/ql/src/semmle/javascript/MembershipCandidates.qll +++ b/javascript/ql/src/semmle/javascript/MembershipCandidates.qll @@ -222,27 +222,27 @@ module MembershipCandidate { */ class ObjectPropertyNameMembershipCandidate extends MembershipCandidate::Range, DataFlow::ValueNode { - DataFlow::ValueNode test; - DataFlow::ValueNode membersNode; + Expr test; + Expr membersNode; ObjectPropertyNameMembershipCandidate() { exists(InExpr inExpr | this = inExpr.getLeftOperand().flow() and - test = inExpr.flow() and - membersNode = inExpr.getRightOperand().flow() + test = inExpr and + membersNode = inExpr.getRightOperand() ) or - exists(DataFlow::MethodCallNode hasOwn | - this = hasOwn.getArgument(0) and + exists(MethodCallExpr hasOwn | + this = hasOwn.getArgument(0).flow() and test = hasOwn and hasOwn.calls(membersNode, "hasOwnProperty") ) } - override DataFlow::Node getTest() { result = test } + override DataFlow::Node getTest() { result = test.flow() } override string getAMemberString() { - exists(membersNode.getALocalSource().getAPropertyWrite(result)) + exists(membersNode.flow().getALocalSource().getAPropertyWrite(result)) } } diff --git a/javascript/ql/src/semmle/javascript/Modules.qll b/javascript/ql/src/semmle/javascript/Modules.qll index 068b3de8dca..038b4d56faf 100644 --- a/javascript/ql/src/semmle/javascript/Modules.qll +++ b/javascript/ql/src/semmle/javascript/Modules.qll @@ -107,6 +107,7 @@ abstract class Module extends TopLevel { * Symbols defined in another module that are re-exported by * this module are only sometimes considered. */ + cached abstract DataFlow::Node getAnExportedValue(string name); /** diff --git a/javascript/ql/src/semmle/javascript/Regexp.qll b/javascript/ql/src/semmle/javascript/Regexp.qll index 485848f40c4..a4612c3b49f 100644 --- a/javascript/ql/src/semmle/javascript/Regexp.qll +++ b/javascript/ql/src/semmle/javascript/Regexp.qll @@ -865,6 +865,17 @@ predicate isInterpretedAsRegExp(DataFlow::Node source) { // because `String.prototype.search` returns a number not exists(PropAccess p | p.getBase() = mce.getEnclosingExpr()) ) + or + exists(DataFlow::SourceNode schema | schema = JsonSchema::getAPartOfJsonSchema() | + source = schema.getAPropertyWrite("pattern").getRhs() + or + source = + schema + .getAPropertySource("patternProperties") + .getAPropertyWrite() + .getPropertyNameExpr() + .flow() + ) ) } diff --git a/javascript/ql/src/semmle/javascript/SSA.qll b/javascript/ql/src/semmle/javascript/SSA.qll index adf53803241..6d330f3fc01 100644 --- a/javascript/ql/src/semmle/javascript/SSA.qll +++ b/javascript/ql/src/semmle/javascript/SSA.qll @@ -520,7 +520,10 @@ class SsaExplicitDefinition extends SsaDefinition, TExplicitDef { override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - getDef().getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + exists(Location loc | + pragma[only_bind_into](loc) = pragma[only_bind_into](getDef()).getLocation() and + loc.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + ) } /** @@ -552,7 +555,10 @@ abstract class SsaImplicitDefinition extends SsaDefinition { ) { endline = startline and endcolumn = startcolumn and - getBasicBlock().getLocation().hasLocationInfo(filepath, startline, startcolumn, _, _) + exists(Location loc | + pragma[only_bind_into](loc) = pragma[only_bind_into](getBasicBlock()).getLocation() and + loc.hasLocationInfo(filepath, startline, startcolumn, _, _) + ) } } @@ -660,14 +666,6 @@ class SsaPhiNode extends SsaPseudoDefinition, TPhi { override string prettyPrintDef() { result = getSourceVariable() + " = phi(" + ppInputs() + ")" } - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - endline = startline and - endcolumn = startcolumn and - getBasicBlock().getLocation().hasLocationInfo(filepath, startline, startcolumn, _, _) - } - /** * If all inputs to this phi node are (transitive) refinements of the same variable, * gets that variable. diff --git a/javascript/ql/src/semmle/javascript/Stmt.qll b/javascript/ql/src/semmle/javascript/Stmt.qll index b1f66a19bf6..1d96c2666ee 100644 --- a/javascript/ql/src/semmle/javascript/Stmt.qll +++ b/javascript/ql/src/semmle/javascript/Stmt.qll @@ -95,7 +95,7 @@ class ControlStmt extends TControlStmt, Stmt { } /** - * A loop, that is, is a while loop, a do-while loop, a for loop, or a for-in loop. + * A loop, that is, a while loop, a do-while loop, a for loop, or a for-in loop. * * Examples: * diff --git a/javascript/ql/src/semmle/javascript/TypeScript.qll b/javascript/ql/src/semmle/javascript/TypeScript.qll index a1b312411ac..4fe263c8389 100644 --- a/javascript/ql/src/semmle/javascript/TypeScript.qll +++ b/javascript/ql/src/semmle/javascript/TypeScript.qll @@ -2149,18 +2149,23 @@ class TupleType extends ArrayType, @tuple_type { int getMinimumLength() { tuple_type_min_length(this, result) } /** - * Holds if this tuple type ends with a rest element, such as `[number, ...string[]]`. + * Gets the index of the rest element. + * For example, for a type `[number, ...string[]]` the result is 1, + * or for a type `[...number[], string]` the result is 0. */ - predicate hasRestElement() { tuple_type_rest(this) } + int getRestElementIndex() { tuple_type_rest_index(this, result) } + + /** + * Holds if this tuple type has a rest element, such as `[number, ...string[]]` or `[...number[], string]`. + */ + predicate hasRestElement() { exists(getRestElementIndex()) } /** * Gets the type of the rest element, if there is one. * * For example, the rest element of `[number, ...string[]]` is `string`. */ - Type getRestElementType() { - hasRestElement() and result = getElementType(getNumElementType() - 1) - } + Type getRestElementType() { result = getElementType(getRestElementIndex()) } } /** @@ -2789,6 +2794,11 @@ class CallSignatureType extends @signature_type { * For example, for the signature `(...y: string[])`, this gets the type `string[]`. */ PlainArrayType getRestParameterArrayType() { signature_rest_parameter(this, result) } + + /** + * Holds if this signature is abstract. + */ + predicate isAbstract() { is_abstract_signature(this) } } /** diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index 3a619033e3c..595917fa6ed 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -106,7 +106,11 @@ module DataFlow { /** Holds if this node may evaluate to the Boolean value `b`. */ predicate mayHaveBooleanValue(boolean b) { - b = analyze().getAValue().(AbstractBoolean).getBooleanValue() + getAPredecessor().mayHaveBooleanValue(b) + or + b = true and asExpr().(BooleanLiteral).getValue() = "true" + or + b = false and asExpr().(BooleanLiteral).getValue() = "false" } /** Gets the integer value of this node, if it is an integer constant. */ diff --git a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll index 65e3c9854e5..741f128059c 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll @@ -168,7 +168,13 @@ class InvokeNode extends DataFlow::SourceNode { private ObjectLiteralNode getOptionsArgument(int i) { result.flowsTo(getArgument(i)) } /** Gets an abstract value representing possible callees of this call site. */ - final AbstractValue getACalleeValue() { result = getCalleeNode().analyze().getAValue() } + final AbstractValue getACalleeValue() { + exists(DataFlow::Node callee, DataFlow::AnalyzedNode analyzed | + pragma[only_bind_into](callee) = getCalleeNode() and + pragma[only_bind_into](analyzed) = callee.analyze() and + pragma[only_bind_into](result) = analyzed.getAValue() + ) + } /** * Gets a potential callee of this call site. @@ -1166,6 +1172,16 @@ module ClassNode { result.getFile() = f } + /** + * Gets a reference to the function `func`, where there exists a read/write of the "prototype" property on that reference. + */ + pragma[noinline] + private DataFlow::SourceNode getAFunctionValueWithPrototype(AbstractValue func) { + exists(result.getAPropertyReference("prototype")) and + result.analyze().getAValue() = pragma[only_bind_into](func) and + func instanceof AbstractFunction // the join-order goes bad if `func` has type `AbstractFunction`. + } + /** * A function definition with prototype manipulation as a `ClassNode` instance. */ @@ -1176,10 +1192,7 @@ module ClassNode { FunctionStyleClass() { function.getFunction() = astNode and ( - exists(DataFlow::PropRef read | - read.getPropertyName() = "prototype" and - read.getBase().analyze().getAValue() = function - ) + exists(getAFunctionValueWithPrototype(function)) or exists(string name | this = AccessPath::getAnAssignmentTo(name) and @@ -1240,7 +1253,7 @@ module ClassNode { * Gets a reference to the prototype of this class. */ DataFlow::SourceNode getAPrototypeReference() { - exists(DataFlow::SourceNode base | base.analyze().getAValue() = function | + exists(DataFlow::SourceNode base | base = getAFunctionValueWithPrototype(function) | result = base.getAPropertyRead("prototype") or result = base.getAPropertySource("prototype") diff --git a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll index ebfdc874f64..451ad3f24d2 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll @@ -854,4 +854,24 @@ module ClientRequest { override DataFlow::Node getADataNode() { none() } } } + + /** + * A model of a URL request made using [form-data](https://www.npmjs.com/package/form-data). + */ + class FormDataRequest extends ClientRequest::Range, API::InvokeNode { + API::Node form; + + FormDataRequest() { + form = API::moduleImport("form-data").getInstance() and + this = form.getMember("submit").getACall() + } + + override DataFlow::Node getUrl() { result = getArgument(0) } + + override DataFlow::Node getHost() { result = getParameter(0).getMember("host").getARhs() } + + override DataFlow::Node getADataNode() { + result = form.getMember("append").getACall().getParameter(1).getARhs() + } + } } diff --git a/javascript/ql/src/semmle/javascript/frameworks/CryptoLibraries.qll b/javascript/ql/src/semmle/javascript/frameworks/CryptoLibraries.qll index a48291d98e2..f8c942ff6b0 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/CryptoLibraries.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/CryptoLibraries.qll @@ -3,175 +3,7 @@ */ import javascript - -/** - * Names of cryptographic algorithms, separated into strong and weak variants. - * - * The names are normalized: upper-case, no spaces, dashes or underscores. - * - * The names are inspired by the names used in real world crypto libraries. - * - * The classification into strong and weak are based on Wikipedia, OWASP and google (2017). - */ -private module AlgorithmNames { - predicate isStrongHashingAlgorithm(string name) { - name = "DSA" or - name = "ED25519" or - name = "ES256" or - name = "ECDSA256" or - name = "ES384" or - name = "ECDSA384" or - name = "ES512" or - name = "ECDSA512" or - name = "SHA2" or - name = "SHA224" or - name = "SHA256" or - name = "SHA384" or - name = "SHA512" or - name = "SHA3" - } - - predicate isWeakHashingAlgorithm(string name) { - name = "HAVEL128" or - name = "MD2" or - name = "MD4" or - name = "MD5" or - name = "PANAMA" or - name = "RIPEMD" or - name = "RIPEMD128" or - name = "RIPEMD256" or - name = "RIPEMD160" or - name = "RIPEMD320" or - name = "SHA0" or - name = "SHA1" - } - - predicate isStrongEncryptionAlgorithm(string name) { - name = "AES" or - name = "AES128" or - name = "AES192" or - name = "AES256" or - name = "AES512" or - name = "RSA" or - name = "RABBIT" or - name = "BLOWFISH" - } - - predicate isWeakEncryptionAlgorithm(string name) { - name = "DES" or - name = "3DES" or - name = "TRIPLEDES" or - name = "TDEA" or - name = "TRIPLEDEA" or - name = "ARC2" or - name = "RC2" or - name = "ARC4" or - name = "RC4" or - name = "ARCFOUR" or - name = "ARC5" or - name = "RC5" - } - - predicate isStrongPasswordHashingAlgorithm(string name) { - name = "ARGON2" or - name = "PBKDF2" or - name = "BCRYPT" or - name = "SCRYPT" - } - - predicate isWeakPasswordHashingAlgorithm(string name) { none() } -} - -private import AlgorithmNames - -/** - * A cryptographic algorithm. - */ -private newtype TCryptographicAlgorithm = - MkHashingAlgorithm(string name, boolean isWeak) { - isStrongHashingAlgorithm(name) and isWeak = false - or - isWeakHashingAlgorithm(name) and isWeak = true - } or - MkEncryptionAlgorithm(string name, boolean isWeak) { - isStrongEncryptionAlgorithm(name) and isWeak = false - or - isWeakEncryptionAlgorithm(name) and isWeak = true - } or - MkPasswordHashingAlgorithm(string name, boolean isWeak) { - isStrongPasswordHashingAlgorithm(name) and isWeak = false - or - isWeakPasswordHashingAlgorithm(name) and isWeak = true - } - -/** - * A cryptographic algorithm. - */ -abstract class CryptographicAlgorithm extends TCryptographicAlgorithm { - /** Gets a textual representation of this element. */ - string toString() { result = getName() } - - /** - * Gets the name of this algorithm. - */ - abstract string getName(); - - /** - * Holds if the name of this algorithm matches `name` modulo case, - * white space, dashes and underscores. - */ - bindingset[name] - predicate matchesName(string name) { - name.toUpperCase().regexpReplaceAll("[-_ ]", "") = getName() - } - - /** - * Holds if this algorithm is weak. - */ - abstract predicate isWeak(); -} - -/** - * A hashing algorithm such as `MD5` or `SHA512`. - */ -class HashingAlgorithm extends MkHashingAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - - HashingAlgorithm() { this = MkHashingAlgorithm(name, isWeak) } - - override string getName() { result = name } - - override predicate isWeak() { isWeak = true } -} - -/** - * An encryption algorithm such as `DES` or `AES512`. - */ -class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - - EncryptionAlgorithm() { this = MkEncryptionAlgorithm(name, isWeak) } - - override string getName() { result = name } - - override predicate isWeak() { isWeak = true } -} - -/** - * A password hashing algorithm such as `PBKDF2` or `SCRYPT`. - */ -class PasswordHashingAlgorithm extends MkPasswordHashingAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - - PasswordHashingAlgorithm() { this = MkPasswordHashingAlgorithm(name, isWeak) } - - override string getName() { result = name } - - override predicate isWeak() { isWeak = true } -} +import semmle.javascript.security.CryptoAlgorithms /** * An application of a cryptographic algorithm. diff --git a/javascript/ql/src/semmle/javascript/frameworks/Hapi.qll b/javascript/ql/src/semmle/javascript/frameworks/Hapi.qll index 3d9e08a9ceb..980ee9b0970 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Hapi.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Hapi.qll @@ -196,11 +196,14 @@ module Hapi { private DataFlow::SourceNode getARouteHandler(DataFlow::TypeBackTracker t) { t.start() and - result = handler.flow().getALocalSource() + result = getRouteHandler().getALocalSource() or exists(DataFlow::TypeBackTracker t2 | result = getARouteHandler(t2).backtrack(t2, t)) } + pragma[noinline] + private DataFlow::Node getRouteHandler() { result = handler.flow() } + Expr getRouteHandlerExpr() { result = handler } override Expr getServer() { result = server } diff --git a/javascript/ql/src/semmle/javascript/frameworks/HttpProxy.qll b/javascript/ql/src/semmle/javascript/frameworks/HttpProxy.qll new file mode 100644 index 00000000000..25f30a876d2 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/frameworks/HttpProxy.qll @@ -0,0 +1,97 @@ +/** + * Provides classes and predicates for working with the [http-proxy](https://www.npmjs.com/package/http-proxy) library. + */ + +import javascript + +/** + * Provides classes and predicates modelling the [http-proxy](https://www.npmjs.com/package/http-proxy) library. + */ +private module HttpProxy { + /** + * A call that creates a http proxy. + */ + class CreateServerCall extends API::CallNode, ClientRequest::Range { + CreateServerCall() { + this = + API::moduleImport("http-proxy") + .getMember(["createServer", "createProxyServer", "createProxy"]) + .getACall() + } + + override DataFlow::Node getUrl() { result = getParameter(0).getMember("target").getARhs() } + + override DataFlow::Node getHost() { + result = getParameter(0).getMember("target").getMember("host").getARhs() + } + + override DataFlow::Node getADataNode() { none() } + } + + /** + * A call that proxies a request to some target. + */ + class ProxyCall extends API::CallNode, ClientRequest::Range { + string method; + + ProxyCall() { + method = ["ws", "web"] and + this = any(CreateServerCall server).getReturn().getMember(method).getACall() + } + + private API::Node getOptionsObject() { + exists(int optionsIndex | + method = "web" and optionsIndex = 2 + or + method = "ws" and optionsIndex = 3 + | + result = getParameter(optionsIndex) + ) + } + + override DataFlow::Node getUrl() { result = getOptionsObject().getMember("target").getARhs() } + + override DataFlow::Node getHost() { + result = getOptionsObject().getMember("target").getMember("host").getARhs() + } + + override DataFlow::Node getADataNode() { none() } + } + + /** + * Holds if an event handler for `event` has a HTTP request parameter at `req` and a HTTP response parameter at `res`. + */ + predicate routeHandlingEventHandler(string event, int req, int res) { + event = ["start", "end"] and req = 0 and res = 1 + or + event = ["proxyReq", "proxyRes", "econnreset"] and req = 1 and res = 2 + or + event = "proxyReqWs" and req = 1 and res = -10 // -10 for non-existent. + } + + /** + * An http proxy event handler. + */ + class ProxyListenerCallback extends NodeJSLib::RouteHandler, DataFlow::FunctionNode { + string event; + API::CallNode call; + + ProxyListenerCallback() { + call = any(CreateServerCall server).getReturn().getMember(["on", "once"]).getACall() and + call.getParameter(0).getARhs().mayHaveStringValue(event) and + this = call.getParameter(1).getARhs().getAFunctionValue() + } + + override Parameter getRequestParameter() { + exists(int req | routeHandlingEventHandler(event, req, _) | + result = getFunction().getParameter(req) + ) + } + + override Parameter getResponseParameter() { + exists(int res | routeHandlingEventHandler(event, _, res) | + result = getFunction().getParameter(res) + ) + } + } +} diff --git a/javascript/ql/src/semmle/javascript/frameworks/Testing.qll b/javascript/ql/src/semmle/javascript/frameworks/Testing.qll index 631ed3b4611..fb2d85523d4 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Testing.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Testing.qll @@ -33,7 +33,7 @@ class BDDTest extends Test, @call_expr { exists(CallExpr call | call = this | call.getCallee().(VarAccess).getName() = "it" and exists(call.getArgument(0).getStringValue()) and - call.getArgument(1).analyze().getAValue() instanceof AbstractFunction + exists(call.getArgument(1).flow().getAFunctionValue(0)) ) } } @@ -60,7 +60,7 @@ class JestTest extends Test, @call_expr { exists(CallExpr call | call = this | call.getCallee().(GlobalVarAccess).getName() = "test" and exists(call.getArgument(0).getStringValue()) and - call.getArgument(1).analyze().getAValue() instanceof AbstractFunction + exists(call.getArgument(1).flow().getAFunctionValue(0)) ) and getFile() = getTestFile(any(File f), "test") } @@ -94,7 +94,7 @@ class CucumberTest extends Test, @call_expr { exists(DataFlow::ModuleImportNode m, CallExpr call | m.getPath() = "cucumber" and call = m.getAnInvocation().asExpr() and - call.getArgument(0).analyze().getAValue() instanceof AbstractFunction and + exists(call.getArgument(0).flow().getAFunctionValue()) and this = call ) } diff --git a/javascript/ql/src/semmle/javascript/frameworks/jQuery.qll b/javascript/ql/src/semmle/javascript/frameworks/jQuery.qll index 5f5be4a2fc4..1716917282f 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/jQuery.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/jQuery.qll @@ -544,17 +544,17 @@ module JQuery { } /** A source of jQuery objects from the AST-based `JQueryObject` class. */ - private DataFlow::Node legacyObjectSource() { result = any(JQueryObjectInternal e).flow() } + private DataFlow::SourceNode legacyObjectSource() { + result = any(JQueryObjectInternal e).flow().getALocalSource() + } /** Gets a source of jQuery objects. */ private DataFlow::SourceNode objectSource(DataFlow::TypeTracker t) { t.start() and result instanceof ObjectSource::Range or - exists(DataFlow::TypeTracker init | - init.start() and - t = init.smallstep(legacyObjectSource(), result) - ) + t.start() and + result = legacyObjectSource() } /** Gets a data flow node referring to a jQuery object. */ @@ -590,10 +590,6 @@ module JQuery { read.getBase().getALocalSource() = [dollar(), objectRef()] and read.mayHavePropertyName(name) ) - or - // Handle contributed JQuery objects that aren't source nodes (usually parameter uses) - getReceiver() = legacyObjectSource() and - this.(DataFlow::MethodCallNode).getMethodName() = name } /** diff --git a/javascript/ql/src/semmle/javascript/security/CryptoAlgorithms.qll b/javascript/ql/src/semmle/javascript/security/CryptoAlgorithms.qll new file mode 100644 index 00000000000..d9f25b42c9a --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/CryptoAlgorithms.qll @@ -0,0 +1,174 @@ +/** + * Provides classes modeling cryptographic algorithms, separated into strong and weak variants. + * + * The classification into strong and weak are based on Wikipedia, OWASP and google (2017). + */ + +/** + * Names of cryptographic algorithms, separated into strong and weak variants. + * + * The names are normalized: upper-case, no spaces, dashes or underscores. + * + * The names are inspired by the names used in real world crypto libraries. + * + * The classification into strong and weak are based on Wikipedia, OWASP and google (2017). + */ +private module AlgorithmNames { + predicate isStrongHashingAlgorithm(string name) { + name = "DSA" or + name = "ED25519" or + name = "ES256" or + name = "ECDSA256" or + name = "ES384" or + name = "ECDSA384" or + name = "ES512" or + name = "ECDSA512" or + name = "SHA2" or + name = "SHA224" or + name = "SHA256" or + name = "SHA384" or + name = "SHA512" or + name = "SHA3" + } + + predicate isWeakHashingAlgorithm(string name) { + name = "HAVEL128" or + name = "MD2" or + name = "MD4" or + name = "MD5" or + name = "PANAMA" or + name = "RIPEMD" or + name = "RIPEMD128" or + name = "RIPEMD256" or + name = "RIPEMD160" or + name = "RIPEMD320" or + name = "SHA0" or + name = "SHA1" + } + + predicate isStrongEncryptionAlgorithm(string name) { + name = "AES" or + name = "AES128" or + name = "AES192" or + name = "AES256" or + name = "AES512" or + name = "RSA" or + name = "RABBIT" or + name = "BLOWFISH" + } + + predicate isWeakEncryptionAlgorithm(string name) { + name = "DES" or + name = "3DES" or + name = "TRIPLEDES" or + name = "TDEA" or + name = "TRIPLEDEA" or + name = "ARC2" or + name = "RC2" or + name = "ARC4" or + name = "RC4" or + name = "ARCFOUR" or + name = "ARC5" or + name = "RC5" + } + + predicate isStrongPasswordHashingAlgorithm(string name) { + name = "ARGON2" or + name = "PBKDF2" or + name = "BCRYPT" or + name = "SCRYPT" + } + + predicate isWeakPasswordHashingAlgorithm(string name) { none() } +} + +private import AlgorithmNames + +/** + * A cryptographic algorithm. + */ +private newtype TCryptographicAlgorithm = + MkHashingAlgorithm(string name, boolean isWeak) { + isStrongHashingAlgorithm(name) and isWeak = false + or + isWeakHashingAlgorithm(name) and isWeak = true + } or + MkEncryptionAlgorithm(string name, boolean isWeak) { + isStrongEncryptionAlgorithm(name) and isWeak = false + or + isWeakEncryptionAlgorithm(name) and isWeak = true + } or + MkPasswordHashingAlgorithm(string name, boolean isWeak) { + isStrongPasswordHashingAlgorithm(name) and isWeak = false + or + isWeakPasswordHashingAlgorithm(name) and isWeak = true + } + +/** + * A cryptographic algorithm. + */ +abstract class CryptographicAlgorithm extends TCryptographicAlgorithm { + /** Gets a textual representation of this element. */ + string toString() { result = getName() } + + /** + * Gets the normalized name of this algorithm (upper-case, no spaces, dashes or underscores). + */ + abstract string getName(); + + /** + * Holds if the name of this algorithm matches `name` modulo case, + * white space, dashes, and underscores. + */ + bindingset[name] + predicate matchesName(string name) { + name.toUpperCase().regexpReplaceAll("[-_ ]", "") = getName() + } + + /** + * Holds if this algorithm is weak. + */ + abstract predicate isWeak(); +} + +/** + * A hashing algorithm such as `MD5` or `SHA512`. + */ +class HashingAlgorithm extends MkHashingAlgorithm, CryptographicAlgorithm { + string name; + boolean isWeak; + + HashingAlgorithm() { this = MkHashingAlgorithm(name, isWeak) } + + override string getName() { result = name } + + override predicate isWeak() { isWeak = true } +} + +/** + * An encryption algorithm such as `DES` or `AES512`. + */ +class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm { + string name; + boolean isWeak; + + EncryptionAlgorithm() { this = MkEncryptionAlgorithm(name, isWeak) } + + override string getName() { result = name } + + override predicate isWeak() { isWeak = true } +} + +/** + * A password hashing algorithm such as `PBKDF2` or `SCRYPT`. + */ +class PasswordHashingAlgorithm extends MkPasswordHashingAlgorithm, CryptographicAlgorithm { + string name; + boolean isWeak; + + PasswordHashingAlgorithm() { this = MkPasswordHashingAlgorithm(name, isWeak) } + + override string getName() { result = name } + + override predicate isWeak() { isWeak = true } +} diff --git a/javascript/ql/src/semmle/javascript/security/TaintedObject.qll b/javascript/ql/src/semmle/javascript/security/TaintedObject.qll index 7f66594254f..444dec2ae71 100644 --- a/javascript/ql/src/semmle/javascript/security/TaintedObject.qll +++ b/javascript/ql/src/semmle/javascript/security/TaintedObject.qll @@ -16,22 +16,16 @@ import javascript private import semmle.javascript.dataflow.InferredTypes +/** Provides classes and predicates for reasoning about deeply tainted objects. */ module TaintedObject { private import DataFlow + import TaintedObjectCustomizations::TaintedObject - private class TaintedObjectLabel extends FlowLabel { - TaintedObjectLabel() { this = "tainted-object" } + // Materialize flow labels + private class ConcreteTaintedObjectLabel extends TaintedObjectLabel { + ConcreteTaintedObjectLabel() { this = this } } - /** - * Gets the flow label representing a deeply tainted object. - * - * A "tainted object" is an array or object whose property values are all assumed to be tainted as well. - * - * Note that the presence of the this label generally implies the presence of the `taint` label as well. - */ - FlowLabel label() { result instanceof TaintedObjectLabel } - /** * Holds for the flows steps that are relevant for tracking user-controlled JSON objects. */ @@ -79,11 +73,6 @@ module TaintedObject { */ predicate isSource(Node source, FlowLabel label) { source instanceof Source and label = label() } - /** - * A source of a user-controlled deep object. - */ - abstract class Source extends DataFlow::Node { } - /** Request input accesses as a JSON source. */ private class RequestInputAsSource extends Source { RequestInputAsSource() { this.(HTTP::RequestInputAccess).isUserControlledObject() } @@ -120,4 +109,19 @@ module TaintedObject { label = label() } } + + /** + * A sanitizer guard that validates an input against a JSON schema. + */ + private class JsonSchemaValidationGuard extends SanitizerGuard { + JsonSchema::ValidationCall call; + + JsonSchemaValidationGuard() { this = call } + + override predicate sanitizes(boolean outcome, Expr e, FlowLabel label) { + outcome = call.getPolarity() and + e = call.getInput().asExpr() and + label = label() + } + } } diff --git a/javascript/ql/src/semmle/javascript/security/TaintedObjectCustomizations.qll b/javascript/ql/src/semmle/javascript/security/TaintedObjectCustomizations.qll new file mode 100644 index 00000000000..8e0fd38f15a --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/TaintedObjectCustomizations.qll @@ -0,0 +1,28 @@ +/** + * Provides access to the "tainted object" flow label defined in `TaintedObject.qll`, without + * materializing that flow label. + */ + +import javascript + +/** Provides classes and predicates for reasoning about deeply tainted objects. */ +module TaintedObject { + /** A flow label representing a deeply tainted object. */ + abstract class TaintedObjectLabel extends DataFlow::FlowLabel { + TaintedObjectLabel() { this = "tainted-object" } + } + + /** + * Gets the flow label representing a deeply tainted object. + * + * A "tainted object" is an array or object whose property values are all assumed to be tainted as well. + * + * Note that the presence of the this label generally implies the presence of the `taint` label as well. + */ + DataFlow::FlowLabel label() { result instanceof TaintedObjectLabel } + + /** + * A source of a user-controlled deep object. + */ + abstract class Source extends DataFlow::Node { } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DOM.qll b/javascript/ql/src/semmle/javascript/security/dataflow/DOM.qll index 57d5612f35e..f1393dd69c0 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/DOM.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/DOM.qll @@ -229,6 +229,7 @@ private class PostMessageEventParameter extends RemoteFlowSource { * even if the window is opened from a foreign domain. */ private class WindowNameAccess extends RemoteFlowSource { + pragma[nomagic, noinline] WindowNameAccess() { this = DataFlow::globalObjectRef().getAPropertyRead("name") or diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustion.qll b/javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustion.qll new file mode 100644 index 00000000000..31bccc11162 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustion.qll @@ -0,0 +1,41 @@ +/** + * Provides a taint tracking configuration for reasoning about DoS attacks + * due to inefficient handling of user-controlled objects. + */ + +import javascript +import semmle.javascript.security.TaintedObject + +/** + * Provides a taint tracking configuration for reasoning about DoS attacks + * due to inefficient handling of user-controlled objects. + */ +module DeepObjectResourceExhaustion { + import DeepObjectResourceExhaustionCustomizations::DeepObjectResourceExhaustion + + /** + * A taint tracking configuration for reasoning about DoS attacks due to inefficient handling + * of user-controlled objects. + */ + class Configuration extends TaintTracking::Configuration { + Configuration() { this = "DeepObjectResourceExhaustion" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { + source.(Source).getAFlowLabel() = label + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { + sink instanceof Sink and label = TaintedObject::label() + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { + guard instanceof TaintedObject::SanitizerGuard + } + + override predicate isAdditionalFlowStep( + DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl + ) { + TaintedObject::step(src, trg, inlbl, outlbl) + } + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionCustomizations.qll new file mode 100644 index 00000000000..52b3874c8cc --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionCustomizations.qll @@ -0,0 +1,94 @@ +/** + * Provides sources, sinks and sanitizers for reasoning about + * DoS attacks due to inefficient handling of user-controlled objects. + */ + +import javascript +private import semmle.javascript.security.TaintedObjectCustomizations + +/** + * Provides sources, sinks and sanitizers for reasoning about + * DoS attacks due to inefficient handling of user-controlled objects. + */ +module DeepObjectResourceExhaustion { + /** + * A data flow source for inefficient handling of user-controlled objects. + */ + abstract class Source extends DataFlow::Node { + /** Gets a flow label to associate with this source. */ + DataFlow::FlowLabel getAFlowLabel() { result = TaintedObject::label() } + } + + private class TaintedObjectSourceAsSource extends Source { + TaintedObjectSourceAsSource() { this instanceof TaintedObject::Source } + + override DataFlow::FlowLabel getAFlowLabel() { result = TaintedObject::label() } + } + + private class RemoteFlowSourceAsSource extends Source { + RemoteFlowSourceAsSource() { this instanceof RemoteFlowSource } + + override DataFlow::FlowLabel getAFlowLabel() { result.isTaint() } + } + + /** + * A data flow sink for inefficient handling of user-controlled objects. + */ + abstract class Sink extends DataFlow::Node { + /** + * Holds if `link` and `text` should be included in the message to explain + * why the handling of the object is slow. + */ + abstract predicate hasReason(DataFlow::Node link, string text); + } + + /** + * A sanitizer for inefficient handling of user-controlled objects. + */ + abstract class Sanitizer extends DataFlow::Node { } + + /** Gets a node that may refer to an object with `allErrors` set to `true`. */ + private DataFlow::SourceNode allErrorsObject( + DataFlow::TypeTracker t, DataFlow::PropWrite allErrors + ) { + t.start() and + exists(JsonSchema::Ajv::AjvValidationCall call) and // only compute if `ajv` is used + allErrors.getPropertyName() = "allErrors" and + allErrors.getRhs().mayHaveBooleanValue(true) and + result = allErrors.getBase().getALocalSource() + or + exists(ExtendCall call | + allErrorsObject(t.continue(), allErrors).flowsTo(call.getAnOperand()) and + (result = call or result = call.getDestinationOperand().getALocalSource()) + ) + or + exists(DataFlow::ObjectLiteralNode obj | + allErrorsObject(t.continue(), allErrors).flowsTo(obj.getASpreadProperty()) and + result = obj + ) + or + exists(DataFlow::TypeTracker t2 | result = allErrorsObject(t2, allErrors).track(t2, t)) + } + + /** Gets a node that may refer to an object with `allErrors` set to `true`. */ + private DataFlow::SourceNode allErrorsObject(DataFlow::PropWrite allErrors) { + result = allErrorsObject(DataFlow::TypeTracker::end(), allErrors) + } + + /** Argument to an `ajv` validation call configured with `allErrors: true`. */ + private class AjvValidationSink extends Sink { + DataFlow::PropWrite allErrors; + + AjvValidationSink() { + exists(JsonSchema::Ajv::AjvValidationCall call | + this = call.getInput() and + allErrorsObject(allErrors).flowsTo(call.getAnOptionsArg()) + ) + } + + override predicate hasReason(DataFlow::Node link, string text) { + link = allErrors and + text = "allErrors: true" + } + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ExceptionXss.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ExceptionXss.qll index a23e9fecf4c..3340df26e72 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/ExceptionXss.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ExceptionXss.qll @@ -10,6 +10,7 @@ module ExceptionXss { import DomBasedXssCustomizations::DomBasedXss as DomBasedXssCustom import ReflectedXssCustomizations::ReflectedXss as ReflectedXssCustom import Xss as Xss + import Xss::ExceptionXss private import semmle.javascript.dataflow.InferredTypes /** @@ -71,14 +72,9 @@ module ExceptionXss { ) } - /** - * A FlowLabel representing tainted data that has not been thrown in an exception. - * In the js/xss-through-exception query data-flow can only reach a sink after - * the data has been thrown as an exception, and data that has not been thrown - * as an exception therefore has this flow label, and only this flow label, associated with it. - */ - class NotYetThrown extends DataFlow::FlowLabel { - NotYetThrown() { this = "NotYetThrown" } + // Materialize flow labels + private class ConcreteNotYetThrown extends Xss::ExceptionXss::NotYetThrown { + ConcreteNotYetThrown() { this = this } } /** @@ -139,7 +135,7 @@ module ExceptionXss { Configuration() { this = "ExceptionXss" } override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { - source instanceof Xss::Shared::Source and label instanceof NotYetThrown + source.(Xss::ExceptionXss::Source).getAFlowLabel() = label } override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll index 387ee8173f2..40a5202a815 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll @@ -14,7 +14,7 @@ module PrototypePollution { * Label for wrappers around tainted objects, that is, objects that are * not completely user-controlled, but contain a user-controlled object. * - * For example, `options` below is is a tainted wrapper, but is not itself + * For example, `options` below is a tainted wrapper, but is not itself * a tainted object: * ``` * let options = { diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/RemoteFlowSources.qll b/javascript/ql/src/semmle/javascript/security/dataflow/RemoteFlowSources.qll index de5ac14d9be..c9d115ee5ea 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/RemoteFlowSources.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/RemoteFlowSources.qll @@ -7,13 +7,16 @@ import semmle.javascript.frameworks.HTTP import semmle.javascript.security.dataflow.DOM /** A data flow source of remote user input. */ +cached abstract class RemoteFlowSource extends DataFlow::Node { /** Gets a string that describes the type of this remote flow source. */ + cached abstract string getSourceType(); /** * Holds if this can be a user-controlled object, such as a JSON object parsed from user-controlled data. */ + cached predicate isUserControlledObject() { none() } } diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/Xss.qll b/javascript/ql/src/semmle/javascript/security/dataflow/Xss.qll index ea911f95300..85b31b90995 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/Xss.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/Xss.qll @@ -602,3 +602,59 @@ module XssThroughDom { /** A data flow source for XSS through DOM vulnerabilities. */ abstract class Source extends Shared::Source { } } + +/** Provides classes for customizing the `ExceptionXss` query. */ +module ExceptionXss { + /** A data flow source for XSS caused by interpreting exception or error text as HTML. */ + abstract class Source extends DataFlow::Node { + /** + * Gets a flow label to associate with this source. + * + * For sources that should pass through a `throw/catch` before reaching the sink, use the + * `NotYetThrown` labe. Otherwise use `taint` (the default). + */ + DataFlow::FlowLabel getAFlowLabel() { result.isTaint() } + + /** + * Gets a human-readable description of what type of error this refers to. + * + * The result should be capitalized and usable in the context of a noun. + */ + string getDescription() { result = "Error text" } + } + + /** + * A FlowLabel representing tainted data that has not been thrown in an exception. + * In the js/xss-through-exception query data-flow can only reach a sink after + * the data has been thrown as an exception, and data that has not been thrown + * as an exception therefore has this flow label, and only this flow label, associated with it. + */ + abstract class NotYetThrown extends DataFlow::FlowLabel { + NotYetThrown() { this = "NotYetThrown" } + } + + private class XssSourceAsSource extends Source { + XssSourceAsSource() { this instanceof Shared::Source } + + override DataFlow::FlowLabel getAFlowLabel() { result instanceof NotYetThrown } + + override string getDescription() { result = "Exception text" } + } + + /** + * An error produced by validating using `ajv`. + * + * Such an error can contain property names from the input if the + * underlying schema uses `additionalProperties` or `propertyPatterns`. + * + * For example, an input of form `{"": 45}` might produce the error + * `data/ should be string`. + */ + private class JsonSchemaValidationError extends Source { + JsonSchemaValidationError() { + this = any(JsonSchema::Ajv::Instance i).getAValidationError().getAnImmediateUse() + } + + override string getDescription() { result = "JSON schema validation error" } + } +} diff --git a/javascript/ql/src/semmlecode.javascript.dbscheme b/javascript/ql/src/semmlecode.javascript.dbscheme index 930898a4fe0..fbd45f6b3c6 100644 --- a/javascript/ql/src/semmlecode.javascript.dbscheme +++ b/javascript/ql/src/semmlecode.javascript.dbscheme @@ -742,6 +742,10 @@ signature_types ( int required_params: int ref ); +is_abstract_signature( + unique int sig: @signature_type ref +); + signature_rest_parameter( unique int sig: @signature_type ref, int rest_param_arra_type: @type ref @@ -799,8 +803,9 @@ tuple_type_min_length( int minLength: int ref ); -tuple_type_rest( - unique int typ: @type ref +tuple_type_rest_index( + unique int typ: @type ref, + int index: int ref ); // comments diff --git a/javascript/ql/src/semmlecode.javascript.dbscheme.stats b/javascript/ql/src/semmlecode.javascript.dbscheme.stats index f5520c0a9e2..206c9bf9fa8 100644 --- a/javascript/ql/src/semmlecode.javascript.dbscheme.stats +++ b/javascript/ql/src/semmlecode.javascript.dbscheme.stats @@ -14480,6 +14480,17 @@ +is_abstract_signature +12 + + +sig +12 + + + + + signature_rest_parameter 19521 @@ -15891,15 +15902,57 @@ -tuple_type_rest -100 +tuple_type_rest_index +6 typ -100 +6 + + +index +2 - + + +typ +index + + +12 + + +1 +2 +6 + + + + + + +index +typ + + +12 + + +1 +2 +1 + + +5 +6 +1 + + + + + + comments diff --git a/javascript/ql/test/library-tests/TypeScript/Nullability/Types.expected b/javascript/ql/test/library-tests/TypeScript/Nullability/Types.expected index f887b4a24c6..6db617b3e77 100644 --- a/javascript/ql/test/library-tests/TypeScript/Nullability/Types.expected +++ b/javascript/ql/test/library-tests/TypeScript/Nullability/Types.expected @@ -3,7 +3,8 @@ exprType | tst.ts:2:5:2:21 | stringOrUndefined | string \| undefined | | tst.ts:3:5:3:27 | stringO ... defined | string \| null \| undefined | | tst.ts:4:5:4:16 | stringOrVoid | string \| void | -| tst.ts:7:5:7:21 | stringOrNullAlias | string \| null | +| tst.ts:7:5:7:21 | stringOrNullAlias | StringOrNullAlias | | tst.ts:8:5:8:32 | stringO ... defined | string \| null \| undefined | | tst.ts:10:5:10:23 | arrayOfStringOrNull | (string \| null)[] | unaliasedType +| StringOrNullAlias | string \| null | diff --git a/javascript/ql/test/library-tests/TypeScript/TypeAliases/TypeAliases.expected b/javascript/ql/test/library-tests/TypeScript/TypeAliases/TypeAliases.expected index 009f58a5bdc..e856d0a1ffa 100644 --- a/javascript/ql/test/library-tests/TypeScript/TypeAliases/TypeAliases.expected +++ b/javascript/ql/test/library-tests/TypeScript/TypeAliases/TypeAliases.expected @@ -3,16 +3,16 @@ rightHandSide | tst.ts:2:1:2:16 | type B = T[]; | T[] | | tst.ts:8:10:8:20 | type C = A; | number | | tst.ts:15:1:15:23 | type Un ... \| Two; | One \| Two | -| tst.ts:17:1:17:36 | type Un ... mber }; | (One & { x: number; }) \| (Two & { x: number; }) | -| tst.ts:18:1:18:21 | type Un ... Union2; | (One & { x: number; }) \| (Two & { x: number; }) | -| tst.ts:19:1:19:21 | type Un ... Union3; | (One & { x: number; }) \| (Two & { x: number; }) | -| tst.ts:20:1:20:30 | type Un ... number; | number \| (One & { x: number; }) \| (Two & { x: n... | +| tst.ts:17:1:17:36 | type Un ... mber }; | Union & { x: number; } | +| tst.ts:18:1:18:21 | type Un ... Union2; | Union & { x: number; } | +| tst.ts:19:1:19:21 | type Un ... Union3; | Union & { x: number; } | +| tst.ts:20:1:20:30 | type Un ... number; | number \| Union2 | getAliasedType | B | T[] | | B | number[] | | Union | One \| Two | -| Union2 | (One & { x: number; }) \| (Two & { x: number; }) | -| Union5 | number \| (One & { x: number; }) \| (Two & { x: n... | +| Union2 | Union & { x: number; } | +| Union5 | number \| Union2 | getTypeArgument | B | 0 | T | | B | 0 | number | diff --git a/javascript/ql/test/library-tests/TypeScript/Types/middle-rest.ts b/javascript/ql/test/library-tests/TypeScript/Types/middle-rest.ts new file mode 100644 index 00000000000..4ca8c74d334 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/Types/middle-rest.ts @@ -0,0 +1,3 @@ +let foo: [boolean, ...string[], number]; + +foo = [true, "hello", 123]; \ No newline at end of file diff --git a/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected b/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected index 357da6a0263..bd50eaa28ec 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected +++ b/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected @@ -84,50 +84,68 @@ nodes | file://:0:0:0:0 | (TypeParameters) | semmle.label | (TypeParameters) | | file://:0:0:0:0 | (TypeParameters) | semmle.label | (TypeParameters) | | file://:0:0:0:0 | (TypeParameters) | semmle.label | (TypeParameters) | +| middle-rest.ts:1:1:1:40 | [DeclStmt] let foo = ... | semmle.label | [DeclStmt] let foo = ... | +| middle-rest.ts:1:1:1:40 | [DeclStmt] let foo = ... | semmle.order | 13 | +| middle-rest.ts:1:5:1:7 | [VarDecl] foo | semmle.label | [VarDecl] foo | +| middle-rest.ts:1:5:1:39 | [VariableDeclarator] foo: [b ... number] | semmle.label | [VariableDeclarator] foo: [b ... number] | +| middle-rest.ts:1:10:1:39 | [TupleTypeExpr] [boolea ... number] | semmle.label | [TupleTypeExpr] [boolea ... number] | +| middle-rest.ts:1:11:1:17 | [KeywordTypeExpr] boolean | semmle.label | [KeywordTypeExpr] boolean | +| middle-rest.ts:1:20:1:30 | [RestTypeExpr] ...string[] | semmle.label | [RestTypeExpr] ...string[] | +| middle-rest.ts:1:23:1:28 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | +| middle-rest.ts:1:23:1:30 | [ArrayTypeExpr] string[] | semmle.label | [ArrayTypeExpr] string[] | +| middle-rest.ts:1:33:1:38 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | +| middle-rest.ts:3:1:3:3 | [VarRef] foo | semmle.label | [VarRef] foo | +| middle-rest.ts:3:1:3:26 | [AssignExpr] foo = [ ... ", 123] | semmle.label | [AssignExpr] foo = [ ... ", 123] | +| middle-rest.ts:3:1:3:27 | [ExprStmt] foo = [ ... , 123]; | semmle.label | [ExprStmt] foo = [ ... , 123]; | +| middle-rest.ts:3:1:3:27 | [ExprStmt] foo = [ ... , 123]; | semmle.order | 14 | +| middle-rest.ts:3:7:3:26 | [ArrayExpr] [true, "hello", 123] | semmle.label | [ArrayExpr] [true, "hello", 123] | +| middle-rest.ts:3:8:3:11 | [Literal] true | semmle.label | [Literal] true | +| middle-rest.ts:3:14:3:20 | [Literal] "hello" | semmle.label | [Literal] "hello" | +| middle-rest.ts:3:23:3:25 | [Literal] 123 | semmle.label | [Literal] 123 | | tst.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; | -| tst.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 13 | +| tst.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 15 | | tst.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy | | tst.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy | | tst.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" | | tst.ts:3:1:3:19 | [DeclStmt] var numVar = ... | semmle.label | [DeclStmt] var numVar = ... | -| tst.ts:3:1:3:19 | [DeclStmt] var numVar = ... | semmle.order | 14 | +| tst.ts:3:1:3:19 | [DeclStmt] var numVar = ... | semmle.order | 16 | | tst.ts:3:5:3:10 | [VarDecl] numVar | semmle.label | [VarDecl] numVar | | tst.ts:3:5:3:18 | [VariableDeclarator] numVar: number | semmle.label | [VariableDeclarator] numVar: number | | tst.ts:3:13:3:18 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | tst.ts:5:1:5:18 | [DeclStmt] var num1 = ... | semmle.label | [DeclStmt] var num1 = ... | -| tst.ts:5:1:5:18 | [DeclStmt] var num1 = ... | semmle.order | 15 | +| tst.ts:5:1:5:18 | [DeclStmt] var num1 = ... | semmle.order | 17 | | tst.ts:5:5:5:8 | [VarDecl] num1 | semmle.label | [VarDecl] num1 | | tst.ts:5:5:5:17 | [VariableDeclarator] num1 = numVar | semmle.label | [VariableDeclarator] num1 = numVar | | tst.ts:5:12:5:17 | [VarRef] numVar | semmle.label | [VarRef] numVar | | tst.ts:6:1:6:13 | [DeclStmt] var num2 = ... | semmle.label | [DeclStmt] var num2 = ... | -| tst.ts:6:1:6:13 | [DeclStmt] var num2 = ... | semmle.order | 16 | +| tst.ts:6:1:6:13 | [DeclStmt] var num2 = ... | semmle.order | 18 | | tst.ts:6:5:6:8 | [VarDecl] num2 | semmle.label | [VarDecl] num2 | | tst.ts:6:5:6:12 | [VariableDeclarator] num2 = 5 | semmle.label | [VariableDeclarator] num2 = 5 | | tst.ts:6:12:6:12 | [Literal] 5 | semmle.label | [Literal] 5 | | tst.ts:7:1:7:23 | [DeclStmt] var num3 = ... | semmle.label | [DeclStmt] var num3 = ... | -| tst.ts:7:1:7:23 | [DeclStmt] var num3 = ... | semmle.order | 17 | +| tst.ts:7:1:7:23 | [DeclStmt] var num3 = ... | semmle.order | 19 | | tst.ts:7:5:7:8 | [VarDecl] num3 | semmle.label | [VarDecl] num3 | | tst.ts:7:5:7:22 | [VariableDeclarator] num3 = num1 + num2 | semmle.label | [VariableDeclarator] num3 = num1 + num2 | | tst.ts:7:12:7:15 | [VarRef] num1 | semmle.label | [VarRef] num1 | | tst.ts:7:12:7:22 | [BinaryExpr] num1 + num2 | semmle.label | [BinaryExpr] num1 + num2 | | tst.ts:7:19:7:22 | [VarRef] num2 | semmle.label | [VarRef] num2 | | tst.ts:9:1:9:19 | [DeclStmt] var strVar = ... | semmle.label | [DeclStmt] var strVar = ... | -| tst.ts:9:1:9:19 | [DeclStmt] var strVar = ... | semmle.order | 18 | +| tst.ts:9:1:9:19 | [DeclStmt] var strVar = ... | semmle.order | 20 | | tst.ts:9:5:9:10 | [VarDecl] strVar | semmle.label | [VarDecl] strVar | | tst.ts:9:5:9:18 | [VariableDeclarator] strVar: string | semmle.label | [VariableDeclarator] strVar: string | | tst.ts:9:13:9:18 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | | tst.ts:10:1:10:20 | [DeclStmt] var hello = ... | semmle.label | [DeclStmt] var hello = ... | -| tst.ts:10:1:10:20 | [DeclStmt] var hello = ... | semmle.order | 19 | +| tst.ts:10:1:10:20 | [DeclStmt] var hello = ... | semmle.order | 21 | | tst.ts:10:5:10:9 | [VarDecl] hello | semmle.label | [VarDecl] hello | | tst.ts:10:5:10:19 | [VariableDeclarator] hello = "hello" | semmle.label | [VariableDeclarator] hello = "hello" | | tst.ts:10:13:10:19 | [Literal] "hello" | semmle.label | [Literal] "hello" | | tst.ts:11:1:11:20 | [DeclStmt] var world = ... | semmle.label | [DeclStmt] var world = ... | -| tst.ts:11:1:11:20 | [DeclStmt] var world = ... | semmle.order | 20 | +| tst.ts:11:1:11:20 | [DeclStmt] var world = ... | semmle.order | 22 | | tst.ts:11:5:11:9 | [VarDecl] world | semmle.label | [VarDecl] world | | tst.ts:11:5:11:19 | [VariableDeclarator] world = "world" | semmle.label | [VariableDeclarator] world = "world" | | tst.ts:11:13:11:19 | [Literal] "world" | semmle.label | [Literal] "world" | | tst.ts:12:1:12:30 | [DeclStmt] var msg = ... | semmle.label | [DeclStmt] var msg = ... | -| tst.ts:12:1:12:30 | [DeclStmt] var msg = ... | semmle.order | 21 | +| tst.ts:12:1:12:30 | [DeclStmt] var msg = ... | semmle.order | 23 | | tst.ts:12:5:12:7 | [VarDecl] msg | semmle.label | [VarDecl] msg | | tst.ts:12:5:12:29 | [VariableDeclarator] msg = h ... + world | semmle.label | [VariableDeclarator] msg = h ... + world | | tst.ts:12:11:12:15 | [VarRef] hello | semmle.label | [VarRef] hello | @@ -136,7 +154,7 @@ nodes | tst.ts:12:19:12:21 | [Literal] " " | semmle.label | [Literal] " " | | tst.ts:12:25:12:29 | [VarRef] world | semmle.label | [VarRef] world | | tst.ts:14:1:14:63 | [FunctionDeclStmt] functio ... + y; } | semmle.label | [FunctionDeclStmt] functio ... + y; } | -| tst.ts:14:1:14:63 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 22 | +| tst.ts:14:1:14:63 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 24 | | tst.ts:14:10:14:15 | [VarDecl] concat | semmle.label | [VarDecl] concat | | tst.ts:14:17:14:17 | [SimpleParameter] x | semmle.label | [SimpleParameter] x | | tst.ts:14:20:14:25 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | @@ -149,7 +167,7 @@ nodes | tst.ts:14:56:14:60 | [BinaryExpr] x + y | semmle.label | [BinaryExpr] x + y | | tst.ts:14:60:14:60 | [VarRef] y | semmle.label | [VarRef] y | | tst.ts:16:1:16:60 | [FunctionDeclStmt] functio ... + y; } | semmle.label | [FunctionDeclStmt] functio ... + y; } | -| tst.ts:16:1:16:60 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 23 | +| tst.ts:16:1:16:60 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 25 | | tst.ts:16:10:16:12 | [VarDecl] add | semmle.label | [VarDecl] add | | tst.ts:16:14:16:14 | [SimpleParameter] x | semmle.label | [SimpleParameter] x | | tst.ts:16:17:16:22 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | @@ -162,7 +180,7 @@ nodes | tst.ts:16:53:16:57 | [BinaryExpr] x + y | semmle.label | [BinaryExpr] x + y | | tst.ts:16:57:16:57 | [VarRef] y | semmle.label | [VarRef] y | | tst.ts:18:1:18:40 | [FunctionDeclStmt] functio ... + y; } | semmle.label | [FunctionDeclStmt] functio ... + y; } | -| tst.ts:18:1:18:40 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 24 | +| tst.ts:18:1:18:40 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 26 | | tst.ts:18:10:18:16 | [VarDecl] untyped | semmle.label | [VarDecl] untyped | | tst.ts:18:18:18:18 | [SimpleParameter] x | semmle.label | [SimpleParameter] x | | tst.ts:18:21:18:21 | [SimpleParameter] y | semmle.label | [SimpleParameter] y | @@ -172,7 +190,7 @@ nodes | tst.ts:18:33:18:37 | [BinaryExpr] x + y | semmle.label | [BinaryExpr] x + y | | tst.ts:18:37:18:37 | [VarRef] y | semmle.label | [VarRef] y | | tst.ts:20:1:20:53 | [FunctionDeclStmt] functio ... + y; } | semmle.label | [FunctionDeclStmt] functio ... + y; } | -| tst.ts:20:1:20:53 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 25 | +| tst.ts:20:1:20:53 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 27 | | tst.ts:20:10:20:21 | [VarDecl] partialTyped | semmle.label | [VarDecl] partialTyped | | tst.ts:20:23:20:23 | [SimpleParameter] x | semmle.label | [SimpleParameter] x | | tst.ts:20:26:20:26 | [SimpleParameter] y | semmle.label | [SimpleParameter] y | @@ -183,7 +201,7 @@ nodes | tst.ts:20:46:20:50 | [BinaryExpr] x + y | semmle.label | [BinaryExpr] x + y | | tst.ts:20:50:20:50 | [VarRef] y | semmle.label | [VarRef] y | | tst.ts:22:1:22:34 | [ForOfStmt] for (le ... 2]) {} | semmle.label | [ForOfStmt] for (le ... 2]) {} | -| tst.ts:22:1:22:34 | [ForOfStmt] for (le ... 2]) {} | semmle.order | 26 | +| tst.ts:22:1:22:34 | [ForOfStmt] for (le ... 2]) {} | semmle.order | 28 | | tst.ts:22:6:22:20 | [DeclStmt] let numFromLoop = ... | semmle.label | [DeclStmt] let numFromLoop = ... | | tst.ts:22:10:22:20 | [VarDecl] numFromLoop | semmle.label | [VarDecl] numFromLoop | | tst.ts:22:10:22:20 | [VariableDeclarator] numFromLoop | semmle.label | [VariableDeclarator] numFromLoop | @@ -192,54 +210,54 @@ nodes | tst.ts:22:29:22:29 | [Literal] 2 | semmle.label | [Literal] 2 | | tst.ts:22:33:22:34 | [BlockStmt] {} | semmle.label | [BlockStmt] {} | | tst.ts:24:1:24:20 | [DeclStmt] let array = ... | semmle.label | [DeclStmt] let array = ... | -| tst.ts:24:1:24:20 | [DeclStmt] let array = ... | semmle.order | 27 | +| tst.ts:24:1:24:20 | [DeclStmt] let array = ... | semmle.order | 29 | | tst.ts:24:5:24:9 | [VarDecl] array | semmle.label | [VarDecl] array | | tst.ts:24:5:24:19 | [VariableDeclarator] array: number[] | semmle.label | [VariableDeclarator] array: number[] | | tst.ts:24:12:24:17 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | tst.ts:24:12:24:19 | [ArrayTypeExpr] number[] | semmle.label | [ArrayTypeExpr] number[] | | tst.ts:26:1:26:25 | [DeclStmt] let voidType = ... | semmle.label | [DeclStmt] let voidType = ... | -| tst.ts:26:1:26:25 | [DeclStmt] let voidType = ... | semmle.order | 28 | +| tst.ts:26:1:26:25 | [DeclStmt] let voidType = ... | semmle.order | 30 | | tst.ts:26:5:26:12 | [VarDecl] voidType | semmle.label | [VarDecl] voidType | | tst.ts:26:5:26:24 | [VariableDeclarator] voidType: () => void | semmle.label | [VariableDeclarator] voidType: () => void | | tst.ts:26:15:26:24 | [FunctionExpr] () => void | semmle.label | [FunctionExpr] () => void | | tst.ts:26:15:26:24 | [FunctionTypeExpr] () => void | semmle.label | [FunctionTypeExpr] () => void | | tst.ts:26:21:26:24 | [KeywordTypeExpr] void | semmle.label | [KeywordTypeExpr] void | | tst.ts:27:1:27:29 | [DeclStmt] let undefinedType = ... | semmle.label | [DeclStmt] let undefinedType = ... | -| tst.ts:27:1:27:29 | [DeclStmt] let undefinedType = ... | semmle.order | 29 | +| tst.ts:27:1:27:29 | [DeclStmt] let undefinedType = ... | semmle.order | 31 | | tst.ts:27:5:27:17 | [VarDecl] undefinedType | semmle.label | [VarDecl] undefinedType | | tst.ts:27:5:27:28 | [VariableDeclarator] undefin ... defined | semmle.label | [VariableDeclarator] undefin ... defined | | tst.ts:27:20:27:28 | [KeywordTypeExpr] undefined | semmle.label | [KeywordTypeExpr] undefined | | tst.ts:28:1:28:26 | [DeclStmt] let nullType = ... | semmle.label | [DeclStmt] let nullType = ... | -| tst.ts:28:1:28:26 | [DeclStmt] let nullType = ... | semmle.order | 30 | +| tst.ts:28:1:28:26 | [DeclStmt] let nullType = ... | semmle.order | 32 | | tst.ts:28:5:28:12 | [VarDecl] nullType | semmle.label | [VarDecl] nullType | | tst.ts:28:5:28:25 | [VariableDeclarator] nullTyp ... = null | semmle.label | [VariableDeclarator] nullTyp ... = null | | tst.ts:28:15:28:18 | [KeywordTypeExpr] null | semmle.label | [KeywordTypeExpr] null | | tst.ts:28:22:28:25 | [Literal] null | semmle.label | [Literal] null | | tst.ts:29:1:29:27 | [DeclStmt] let neverType = ... | semmle.label | [DeclStmt] let neverType = ... | -| tst.ts:29:1:29:27 | [DeclStmt] let neverType = ... | semmle.order | 31 | +| tst.ts:29:1:29:27 | [DeclStmt] let neverType = ... | semmle.order | 33 | | tst.ts:29:5:29:13 | [VarDecl] neverType | semmle.label | [VarDecl] neverType | | tst.ts:29:5:29:26 | [VariableDeclarator] neverTy ... > never | semmle.label | [VariableDeclarator] neverTy ... > never | | tst.ts:29:16:29:26 | [FunctionExpr] () => never | semmle.label | [FunctionExpr] () => never | | tst.ts:29:16:29:26 | [FunctionTypeExpr] () => never | semmle.label | [FunctionTypeExpr] () => never | | tst.ts:29:22:29:26 | [KeywordTypeExpr] never | semmle.label | [KeywordTypeExpr] never | | tst.ts:30:1:30:23 | [DeclStmt] let symbolType = ... | semmle.label | [DeclStmt] let symbolType = ... | -| tst.ts:30:1:30:23 | [DeclStmt] let symbolType = ... | semmle.order | 32 | +| tst.ts:30:1:30:23 | [DeclStmt] let symbolType = ... | semmle.order | 34 | | tst.ts:30:5:30:14 | [VarDecl] symbolType | semmle.label | [VarDecl] symbolType | | tst.ts:30:5:30:22 | [VariableDeclarator] symbolType: symbol | semmle.label | [VariableDeclarator] symbolType: symbol | | tst.ts:30:17:30:22 | [KeywordTypeExpr] symbol | semmle.label | [KeywordTypeExpr] symbol | | tst.ts:31:1:31:45 | [DeclStmt] const uniqueSymbolType = ... | semmle.label | [DeclStmt] const uniqueSymbolType = ... | -| tst.ts:31:1:31:45 | [DeclStmt] const uniqueSymbolType = ... | semmle.order | 33 | +| tst.ts:31:1:31:45 | [DeclStmt] const uniqueSymbolType = ... | semmle.order | 35 | | tst.ts:31:7:31:22 | [VarDecl] uniqueSymbolType | semmle.label | [VarDecl] uniqueSymbolType | | tst.ts:31:7:31:44 | [VariableDeclarator] uniqueS ... = null | semmle.label | [VariableDeclarator] uniqueS ... = null | | tst.ts:31:25:31:37 | [KeywordTypeExpr] unique symbol | semmle.label | [KeywordTypeExpr] unique symbol | | tst.ts:31:41:31:44 | [Literal] null | semmle.label | [Literal] null | | tst.ts:32:1:32:23 | [DeclStmt] let objectType = ... | semmle.label | [DeclStmt] let objectType = ... | -| tst.ts:32:1:32:23 | [DeclStmt] let objectType = ... | semmle.order | 34 | +| tst.ts:32:1:32:23 | [DeclStmt] let objectType = ... | semmle.order | 36 | | tst.ts:32:5:32:14 | [VarDecl] objectType | semmle.label | [VarDecl] objectType | | tst.ts:32:5:32:22 | [VariableDeclarator] objectType: object | semmle.label | [VariableDeclarator] objectType: object | | tst.ts:32:17:32:22 | [KeywordTypeExpr] object | semmle.label | [KeywordTypeExpr] object | | tst.ts:33:1:33:39 | [DeclStmt] let intersection = ... | semmle.label | [DeclStmt] let intersection = ... | -| tst.ts:33:1:33:39 | [DeclStmt] let intersection = ... | semmle.order | 35 | +| tst.ts:33:1:33:39 | [DeclStmt] let intersection = ... | semmle.order | 37 | | tst.ts:33:5:33:16 | [VarDecl] intersection | semmle.label | [VarDecl] intersection | | tst.ts:33:5:33:38 | [VariableDeclarator] interse ... string} | semmle.label | [VariableDeclarator] interse ... string} | | tst.ts:33:19:33:24 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | @@ -249,14 +267,14 @@ nodes | tst.ts:33:29:33:37 | [FieldDeclaration] x: string | semmle.label | [FieldDeclaration] x: string | | tst.ts:33:32:33:37 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | | tst.ts:34:1:34:28 | [DeclStmt] let tuple = ... | semmle.label | [DeclStmt] let tuple = ... | -| tst.ts:34:1:34:28 | [DeclStmt] let tuple = ... | semmle.order | 36 | +| tst.ts:34:1:34:28 | [DeclStmt] let tuple = ... | semmle.order | 38 | | tst.ts:34:5:34:9 | [VarDecl] tuple | semmle.label | [VarDecl] tuple | | tst.ts:34:5:34:27 | [VariableDeclarator] tuple: ... string] | semmle.label | [VariableDeclarator] tuple: ... string] | | tst.ts:34:12:34:27 | [TupleTypeExpr] [number, string] | semmle.label | [TupleTypeExpr] [number, string] | | tst.ts:34:13:34:18 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | tst.ts:34:21:34:26 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | | tst.ts:36:1:36:56 | [DeclStmt] let tupleWithOptionalElement = ... | semmle.label | [DeclStmt] let tupleWithOptionalElement = ... | -| tst.ts:36:1:36:56 | [DeclStmt] let tupleWithOptionalElement = ... | semmle.order | 37 | +| tst.ts:36:1:36:56 | [DeclStmt] let tupleWithOptionalElement = ... | semmle.order | 39 | | tst.ts:36:5:36:28 | [VarDecl] tupleWithOptionalElement | semmle.label | [VarDecl] tupleWithOptionalElement | | tst.ts:36:5:36:55 | [VariableDeclarator] tupleWi ... umber?] | semmle.label | [VariableDeclarator] tupleWi ... umber?] | | tst.ts:36:31:36:55 | [TupleTypeExpr] [number ... umber?] | semmle.label | [TupleTypeExpr] [number ... umber?] | @@ -265,12 +283,12 @@ nodes | tst.ts:36:48:36:53 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | tst.ts:36:48:36:54 | [OptionalTypeExpr] number? | semmle.label | [OptionalTypeExpr] number? | | tst.ts:37:1:37:19 | [DeclStmt] let emptyTuple = ... | semmle.label | [DeclStmt] let emptyTuple = ... | -| tst.ts:37:1:37:19 | [DeclStmt] let emptyTuple = ... | semmle.order | 38 | +| tst.ts:37:1:37:19 | [DeclStmt] let emptyTuple = ... | semmle.order | 40 | | tst.ts:37:5:37:14 | [VarDecl] emptyTuple | semmle.label | [VarDecl] emptyTuple | | tst.ts:37:5:37:18 | [VariableDeclarator] emptyTuple: [] | semmle.label | [VariableDeclarator] emptyTuple: [] | | tst.ts:37:17:37:18 | [TupleTypeExpr] [] | semmle.label | [TupleTypeExpr] [] | | tst.ts:38:1:38:48 | [DeclStmt] let tupleWithRestElement = ... | semmle.label | [DeclStmt] let tupleWithRestElement = ... | -| tst.ts:38:1:38:48 | [DeclStmt] let tupleWithRestElement = ... | semmle.order | 39 | +| tst.ts:38:1:38:48 | [DeclStmt] let tupleWithRestElement = ... | semmle.order | 41 | | tst.ts:38:5:38:24 | [VarDecl] tupleWithRestElement | semmle.label | [VarDecl] tupleWithRestElement | | tst.ts:38:5:38:47 | [VariableDeclarator] tupleWi ... ring[]] | semmle.label | [VariableDeclarator] tupleWi ... ring[]] | | tst.ts:38:27:38:47 | [TupleTypeExpr] [number ... ring[]] | semmle.label | [TupleTypeExpr] [number ... ring[]] | @@ -279,7 +297,7 @@ nodes | tst.ts:38:39:38:44 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | | tst.ts:38:39:38:46 | [ArrayTypeExpr] string[] | semmle.label | [ArrayTypeExpr] string[] | | tst.ts:39:1:39:69 | [DeclStmt] let tupleWithOptionalAndRestElements = ... | semmle.label | [DeclStmt] let tupleWithOptionalAndRestElements = ... | -| tst.ts:39:1:39:69 | [DeclStmt] let tupleWithOptionalAndRestElements = ... | semmle.order | 40 | +| tst.ts:39:1:39:69 | [DeclStmt] let tupleWithOptionalAndRestElements = ... | semmle.order | 42 | | tst.ts:39:5:39:36 | [VarDecl] tupleWithOptionalAndRestElements | semmle.label | [VarDecl] tupleWithOptionalAndRestElements | | tst.ts:39:5:39:68 | [VariableDeclarator] tupleWi ... mber[]] | semmle.label | [VariableDeclarator] tupleWi ... mber[]] | | tst.ts:39:39:39:68 | [TupleTypeExpr] [number ... mber[]] | semmle.label | [TupleTypeExpr] [number ... mber[]] | @@ -290,12 +308,12 @@ nodes | tst.ts:39:60:39:65 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | tst.ts:39:60:39:67 | [ArrayTypeExpr] number[] | semmle.label | [ArrayTypeExpr] number[] | | tst.ts:40:1:40:25 | [DeclStmt] let unknownType = ... | semmle.label | [DeclStmt] let unknownType = ... | -| tst.ts:40:1:40:25 | [DeclStmt] let unknownType = ... | semmle.order | 41 | +| tst.ts:40:1:40:25 | [DeclStmt] let unknownType = ... | semmle.order | 43 | | tst.ts:40:5:40:15 | [VarDecl] unknownType | semmle.label | [VarDecl] unknownType | | tst.ts:40:5:40:24 | [VariableDeclarator] unknownType: unknown | semmle.label | [VariableDeclarator] unknownType: unknown | | tst.ts:40:18:40:24 | [KeywordTypeExpr] unknown | semmle.label | [KeywordTypeExpr] unknown | | tst.ts:42:1:42:40 | [DeclStmt] let constArrayLiteral = ... | semmle.label | [DeclStmt] let constArrayLiteral = ... | -| tst.ts:42:1:42:40 | [DeclStmt] let constArrayLiteral = ... | semmle.order | 42 | +| tst.ts:42:1:42:40 | [DeclStmt] let constArrayLiteral = ... | semmle.order | 44 | | tst.ts:42:5:42:21 | [VarDecl] constArrayLiteral | semmle.label | [VarDecl] constArrayLiteral | | tst.ts:42:5:42:39 | [VariableDeclarator] constAr ... s const | semmle.label | [VariableDeclarator] constAr ... s const | | tst.ts:42:25:42:30 | [ArrayExpr] [1, 2] | semmle.label | [ArrayExpr] [1, 2] | @@ -304,7 +322,7 @@ nodes | tst.ts:42:29:42:29 | [Literal] 2 | semmle.label | [Literal] 2 | | tst.ts:42:35:42:39 | [KeywordTypeExpr] const | semmle.label | [KeywordTypeExpr] const | | tst.ts:43:1:43:49 | [DeclStmt] let constObjectLiteral = ... | semmle.label | [DeclStmt] let constObjectLiteral = ... | -| tst.ts:43:1:43:49 | [DeclStmt] let constObjectLiteral = ... | semmle.order | 43 | +| tst.ts:43:1:43:49 | [DeclStmt] let constObjectLiteral = ... | semmle.order | 45 | | tst.ts:43:5:43:22 | [VarDecl] constObjectLiteral | semmle.label | [VarDecl] constObjectLiteral | | tst.ts:43:5:43:48 | [VariableDeclarator] constOb ... s const | semmle.label | [VariableDeclarator] constOb ... s const | | tst.ts:43:26:43:39 | [ObjectExpr] {foo: ...} | semmle.label | [ObjectExpr] {foo: ...} | @@ -314,7 +332,7 @@ nodes | tst.ts:43:33:43:37 | [Literal] "foo" | semmle.label | [Literal] "foo" | | tst.ts:43:44:43:48 | [KeywordTypeExpr] const | semmle.label | [KeywordTypeExpr] const | | tst.ts:46:1:51:1 | [TryStmt] try { } ... ; } } | semmle.label | [TryStmt] try { } ... ; } } | -| tst.ts:46:1:51:1 | [TryStmt] try { } ... ; } } | semmle.order | 44 | +| tst.ts:46:1:51:1 | [TryStmt] try { } ... ; } } | semmle.order | 46 | | tst.ts:46:5:46:7 | [BlockStmt] { } | semmle.label | [BlockStmt] { } | | tst.ts:47:1:51:1 | [CatchClause] catch ( ... ; } } | semmle.label | [CatchClause] catch ( ... ; } } | | tst.ts:47:8:47:8 | [SimpleParameter] e | semmle.label | [SimpleParameter] e | @@ -330,17 +348,78 @@ nodes | tst.ts:49:11:49:24 | [VariableDeclarator] b : string = e | semmle.label | [VariableDeclarator] b : string = e | | tst.ts:49:15:49:20 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | | tst.ts:49:24:49:24 | [VarRef] e | semmle.label | [VarRef] e | +| tst.ts:54:1:56:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | +| tst.ts:54:1:56:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | semmle.order | 47 | +| tst.ts:54:11:54:26 | [Identifier] NonAbstractDummy | semmle.label | [Identifier] NonAbstractDummy | +| tst.ts:55:3:55:9 | [Label] getArea | semmle.label | [Label] getArea | +| tst.ts:55:3:55:20 | [FunctionExpr] getArea(): number; | semmle.label | [FunctionExpr] getArea(): number; | +| tst.ts:55:3:55:20 | [MethodSignature] getArea(): number; | semmle.label | [MethodSignature] getArea(): number; | +| tst.ts:55:14:55:19 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | +| tst.ts:58:1:60:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | +| tst.ts:58:1:60:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | semmle.order | 48 | +| tst.ts:58:11:58:17 | [Identifier] HasArea | semmle.label | [Identifier] HasArea | +| tst.ts:59:3:59:9 | [Label] getArea | semmle.label | [Label] getArea | +| tst.ts:59:3:59:20 | [FunctionExpr] getArea(): number; | semmle.label | [FunctionExpr] getArea(): number; | +| tst.ts:59:3:59:20 | [MethodSignature] getArea(): number; | semmle.label | [MethodSignature] getArea(): number; | +| tst.ts:59:14:59:19 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | +| tst.ts:63:1:63:45 | [DeclStmt] let Ctor = ... | semmle.label | [DeclStmt] let Ctor = ... | +| tst.ts:63:1:63:45 | [DeclStmt] let Ctor = ... | semmle.order | 49 | +| tst.ts:63:5:63:8 | [VarDecl] Ctor | semmle.label | [VarDecl] Ctor | +| tst.ts:63:5:63:44 | [VariableDeclarator] Ctor: a ... = Shape | semmle.label | [VariableDeclarator] Ctor: a ... = Shape | +| tst.ts:63:11:63:36 | [FunctionExpr] abstrac ... HasArea | semmle.label | [FunctionExpr] abstrac ... HasArea | +| tst.ts:63:11:63:36 | [FunctionTypeExpr] abstrac ... HasArea | semmle.label | [FunctionTypeExpr] abstrac ... HasArea | +| tst.ts:63:30:63:36 | [LocalTypeAccess] HasArea | semmle.label | [LocalTypeAccess] HasArea | +| tst.ts:63:40:63:44 | [VarRef] Shape | semmle.label | [VarRef] Shape | +| tst.ts:65:1:65:54 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | +| tst.ts:65:1:65:54 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | semmle.order | 50 | +| tst.ts:65:6:65:12 | [Identifier] MyUnion | semmle.label | [Identifier] MyUnion | +| tst.ts:65:16:65:30 | [InterfaceTypeExpr] {myUnion: true} | semmle.label | [InterfaceTypeExpr] {myUnion: true} | +| tst.ts:65:16:65:53 | [UnionTypeExpr] {myUnio ... : true} | semmle.label | [UnionTypeExpr] {myUnio ... : true} | +| tst.ts:65:17:65:23 | [Label] myUnion | semmle.label | [Label] myUnion | +| tst.ts:65:17:65:29 | [FieldDeclaration] myUnion: true | semmle.label | [FieldDeclaration] myUnion: true | +| tst.ts:65:26:65:29 | [LiteralTypeExpr] true | semmle.label | [LiteralTypeExpr] true | +| tst.ts:65:34:65:53 | [InterfaceTypeExpr] {stillMyUnion: true} | semmle.label | [InterfaceTypeExpr] {stillMyUnion: true} | +| tst.ts:65:35:65:46 | [Label] stillMyUnion | semmle.label | [Label] stillMyUnion | +| tst.ts:65:35:65:52 | [FieldDeclaration] stillMyUnion: true | semmle.label | [FieldDeclaration] stillMyUnion: true | +| tst.ts:65:49:65:52 | [LiteralTypeExpr] true | semmle.label | [LiteralTypeExpr] true | +| tst.ts:66:1:66:38 | [DeclStmt] let union1 = ... | semmle.label | [DeclStmt] let union1 = ... | +| tst.ts:66:1:66:38 | [DeclStmt] let union1 = ... | semmle.order | 51 | +| tst.ts:66:5:66:10 | [VarDecl] union1 | semmle.label | [VarDecl] union1 | +| tst.ts:66:5:66:37 | [VariableDeclarator] union1: ... : true} | semmle.label | [VariableDeclarator] union1: ... : true} | +| tst.ts:66:13:66:19 | [LocalTypeAccess] MyUnion | semmle.label | [LocalTypeAccess] MyUnion | +| tst.ts:66:23:66:37 | [ObjectExpr] {myUnion: ...} | semmle.label | [ObjectExpr] {myUnion: ...} | +| tst.ts:66:24:66:30 | [Label] myUnion | semmle.label | [Label] myUnion | +| tst.ts:66:24:66:36 | [Property] myUnion: true | semmle.label | [Property] myUnion: true | +| tst.ts:66:33:66:36 | [Literal] true | semmle.label | [Literal] true | +| tst.ts:68:1:68:49 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | +| tst.ts:68:1:68:49 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | semmle.order | 52 | +| tst.ts:68:6:68:13 | [Identifier] MyUnion2 | semmle.label | [Identifier] MyUnion2 | +| tst.ts:68:17:68:23 | [LocalTypeAccess] MyUnion | semmle.label | [LocalTypeAccess] MyUnion | +| tst.ts:68:17:68:48 | [UnionTypeExpr] MyUnion ... : true} | semmle.label | [UnionTypeExpr] MyUnion ... : true} | +| tst.ts:68:27:68:48 | [InterfaceTypeExpr] {yetAno ... : true} | semmle.label | [InterfaceTypeExpr] {yetAno ... : true} | +| tst.ts:68:28:68:41 | [Label] yetAnotherType | semmle.label | [Label] yetAnotherType | +| tst.ts:68:28:68:47 | [FieldDeclaration] yetAnotherType: true | semmle.label | [FieldDeclaration] yetAnotherType: true | +| tst.ts:68:44:68:47 | [LiteralTypeExpr] true | semmle.label | [LiteralTypeExpr] true | +| tst.ts:69:1:69:46 | [DeclStmt] let union2 = ... | semmle.label | [DeclStmt] let union2 = ... | +| tst.ts:69:1:69:46 | [DeclStmt] let union2 = ... | semmle.order | 53 | +| tst.ts:69:5:69:10 | [VarDecl] union2 | semmle.label | [VarDecl] union2 | +| tst.ts:69:5:69:45 | [VariableDeclarator] union2: ... : true} | semmle.label | [VariableDeclarator] union2: ... : true} | +| tst.ts:69:13:69:20 | [LocalTypeAccess] MyUnion2 | semmle.label | [LocalTypeAccess] MyUnion2 | +| tst.ts:69:24:69:45 | [ObjectExpr] {yetAnotherType: ...} | semmle.label | [ObjectExpr] {yetAnotherType: ...} | +| tst.ts:69:25:69:38 | [Label] yetAnotherType | semmle.label | [Label] yetAnotherType | +| tst.ts:69:25:69:44 | [Property] yetAnotherType: true | semmle.label | [Property] yetAnotherType: true | +| tst.ts:69:41:69:44 | [Literal] true | semmle.label | [Literal] true | | type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | -| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.order | 45 | +| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.order | 54 | | type_alias.ts:1:6:1:6 | [Identifier] B | semmle.label | [Identifier] B | | type_alias.ts:1:10:1:16 | [KeywordTypeExpr] boolean | semmle.label | [KeywordTypeExpr] boolean | | type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.label | [DeclStmt] var b = ... | -| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.order | 46 | +| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.order | 55 | | type_alias.ts:3:5:3:5 | [VarDecl] b | semmle.label | [VarDecl] b | | type_alias.ts:3:5:3:8 | [VariableDeclarator] b: B | semmle.label | [VariableDeclarator] b: B | | type_alias.ts:3:8:3:8 | [LocalTypeAccess] B | semmle.label | [LocalTypeAccess] B | | type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | -| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.order | 47 | +| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.order | 56 | | type_alias.ts:5:6:5:17 | [Identifier] ValueOrArray | semmle.label | [Identifier] ValueOrArray | | type_alias.ts:5:19:5:19 | [Identifier] T | semmle.label | [Identifier] T | | type_alias.ts:5:19:5:19 | [TypeParameter] T | semmle.label | [TypeParameter] T | @@ -352,14 +431,14 @@ nodes | type_alias.ts:5:34:5:48 | [GenericTypeExpr] ValueOrArray | semmle.label | [GenericTypeExpr] ValueOrArray | | type_alias.ts:5:47:5:47 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T | | type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.label | [DeclStmt] var c = ... | -| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.order | 48 | +| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.order | 57 | | type_alias.ts:7:5:7:5 | [VarDecl] c | semmle.label | [VarDecl] c | | type_alias.ts:7:5:7:27 | [VariableDeclarator] c: Valu ... number> | semmle.label | [VariableDeclarator] c: Valu ... number> | | type_alias.ts:7:8:7:19 | [LocalTypeAccess] ValueOrArray | semmle.label | [LocalTypeAccess] ValueOrArray | | type_alias.ts:7:8:7:27 | [GenericTypeExpr] ValueOrArray | semmle.label | [GenericTypeExpr] ValueOrArray | | type_alias.ts:7:21:7:26 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | -| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.order | 49 | +| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.order | 58 | | type_alias.ts:9:6:9:9 | [Identifier] Json | semmle.label | [Identifier] Json | | type_alias.ts:10:5:15:12 | [UnionTypeExpr] \| strin ... Json[] | semmle.label | [UnionTypeExpr] \| strin ... Json[] | | type_alias.ts:10:7:10:12 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | @@ -375,12 +454,12 @@ nodes | type_alias.ts:15:7:15:10 | [LocalTypeAccess] Json | semmle.label | [LocalTypeAccess] Json | | type_alias.ts:15:7:15:12 | [ArrayTypeExpr] Json[] | semmle.label | [ArrayTypeExpr] Json[] | | type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.label | [DeclStmt] var json = ... | -| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.order | 50 | +| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.order | 59 | | type_alias.ts:17:5:17:8 | [VarDecl] json | semmle.label | [VarDecl] json | | type_alias.ts:17:5:17:14 | [VariableDeclarator] json: Json | semmle.label | [VariableDeclarator] json: Json | | type_alias.ts:17:11:17:14 | [LocalTypeAccess] Json | semmle.label | [LocalTypeAccess] Json | | type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | -| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.order | 51 | +| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.order | 60 | | type_alias.ts:19:6:19:16 | [Identifier] VirtualNode | semmle.label | [Identifier] VirtualNode | | type_alias.ts:20:5:21:56 | [UnionTypeExpr] \| strin ... Node[]] | semmle.label | [UnionTypeExpr] \| strin ... Node[]] | | type_alias.ts:20:7:20:12 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | @@ -396,7 +475,7 @@ nodes | type_alias.ts:21:43:21:53 | [LocalTypeAccess] VirtualNode | semmle.label | [LocalTypeAccess] VirtualNode | | type_alias.ts:21:43:21:55 | [ArrayTypeExpr] VirtualNode[] | semmle.label | [ArrayTypeExpr] VirtualNode[] | | type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.label | [DeclStmt] const myNode = ... | -| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.order | 52 | +| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.order | 61 | | type_alias.ts:23:7:23:12 | [VarDecl] myNode | semmle.label | [VarDecl] myNode | | type_alias.ts:23:7:27:5 | [VariableDeclarator] myNode: ... ] ] | semmle.label | [VariableDeclarator] myNode: ... ] ] | | type_alias.ts:23:15:23:25 | [LocalTypeAccess] VirtualNode | semmle.label | [LocalTypeAccess] VirtualNode | @@ -421,12 +500,12 @@ nodes | type_alias.ts:26:23:26:36 | [Literal] "second-child" | semmle.label | [Literal] "second-child" | | type_alias.ts:26:41:26:62 | [Literal] "I'm the second child" | semmle.label | [Literal] "I'm the second child" | | type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; | -| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 53 | +| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 62 | | type_definition_objects.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy | | type_definition_objects.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy | | type_definition_objects.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" | | type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.label | [ExportDeclaration] export class C {} | -| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.order | 54 | +| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.order | 63 | | type_definition_objects.ts:3:8:3:17 | [ClassDefinition,TypeDefinition] class C {} | semmle.label | [ClassDefinition,TypeDefinition] class C {} | | type_definition_objects.ts:3:14:3:14 | [VarDecl] C | semmle.label | [VarDecl] C | | type_definition_objects.ts:3:16:3:15 | [BlockStmt] {} | semmle.label | [BlockStmt] {} | @@ -434,36 +513,36 @@ nodes | type_definition_objects.ts:3:16:3:15 | [FunctionExpr] () {} | semmle.label | [FunctionExpr] () {} | | type_definition_objects.ts:3:16:3:15 | [Label] constructor | semmle.label | [Label] constructor | | type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.label | [DeclStmt] let classObj = ... | -| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.order | 55 | +| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.order | 64 | | type_definition_objects.ts:4:5:4:12 | [VarDecl] classObj | semmle.label | [VarDecl] classObj | | type_definition_objects.ts:4:5:4:16 | [VariableDeclarator] classObj = C | semmle.label | [VariableDeclarator] classObj = C | | type_definition_objects.ts:4:16:4:16 | [VarRef] C | semmle.label | [VarRef] C | | type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.label | [ExportDeclaration] export enum E {} | -| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.order | 56 | +| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.order | 65 | | type_definition_objects.ts:6:8:6:16 | [EnumDeclaration,TypeDefinition] enum E {} | semmle.label | [EnumDeclaration,TypeDefinition] enum E {} | | type_definition_objects.ts:6:13:6:13 | [VarDecl] E | semmle.label | [VarDecl] E | | type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.label | [DeclStmt] let enumObj = ... | -| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.order | 57 | +| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.order | 66 | | type_definition_objects.ts:7:5:7:11 | [VarDecl] enumObj | semmle.label | [VarDecl] enumObj | | type_definition_objects.ts:7:5:7:15 | [VariableDeclarator] enumObj = E | semmle.label | [VariableDeclarator] enumObj = E | | type_definition_objects.ts:7:15:7:15 | [VarRef] E | semmle.label | [VarRef] E | | type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.label | [ExportDeclaration] export ... e N {;} | -| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.order | 58 | +| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.order | 67 | | type_definition_objects.ts:9:8:9:22 | [NamespaceDeclaration] namespace N {;} | semmle.label | [NamespaceDeclaration] namespace N {;} | | type_definition_objects.ts:9:18:9:18 | [VarDecl] N | semmle.label | [VarDecl] N | | type_definition_objects.ts:9:21:9:21 | [EmptyStmt] ; | semmle.label | [EmptyStmt] ; | | type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.label | [DeclStmt] let namespaceObj = ... | -| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.order | 59 | +| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.order | 68 | | type_definition_objects.ts:10:5:10:16 | [VarDecl] namespaceObj | semmle.label | [VarDecl] namespaceObj | | type_definition_objects.ts:10:5:10:20 | [VariableDeclarator] namespaceObj = N | semmle.label | [VariableDeclarator] namespaceObj = N | | type_definition_objects.ts:10:20:10:20 | [VarRef] N | semmle.label | [VarRef] N | | type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; | -| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 60 | +| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 69 | | type_definitions.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy | | type_definitions.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy | | type_definitions.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" | | type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | -| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.order | 61 | +| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.order | 70 | | type_definitions.ts:3:11:3:11 | [Identifier] I | semmle.label | [Identifier] I | | type_definitions.ts:3:13:3:13 | [Identifier] S | semmle.label | [Identifier] S | | type_definitions.ts:3:13:3:13 | [TypeParameter] S | semmle.label | [TypeParameter] S | @@ -471,14 +550,14 @@ nodes | type_definitions.ts:4:3:4:7 | [FieldDeclaration] x: S; | semmle.label | [FieldDeclaration] x: S; | | type_definitions.ts:4:6:4:6 | [LocalTypeAccess] S | semmle.label | [LocalTypeAccess] S | | type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.label | [DeclStmt] let i = ... | -| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.order | 62 | +| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.order | 71 | | type_definitions.ts:6:5:6:5 | [VarDecl] i | semmle.label | [VarDecl] i | | type_definitions.ts:6:5:6:16 | [VariableDeclarator] i: I | semmle.label | [VariableDeclarator] i: I | | type_definitions.ts:6:8:6:8 | [LocalTypeAccess] I | semmle.label | [LocalTypeAccess] I | | type_definitions.ts:6:8:6:16 | [GenericTypeExpr] I | semmle.label | [GenericTypeExpr] I | | type_definitions.ts:6:10:6:15 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.label | [ClassDefinition,TypeDefinition] class C ... x: T } | -| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.order | 63 | +| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.order | 72 | | type_definitions.ts:8:7:8:7 | [VarDecl] C | semmle.label | [VarDecl] C | | type_definitions.ts:8:8:8:7 | [BlockStmt] {} | semmle.label | [BlockStmt] {} | | type_definitions.ts:8:8:8:7 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | semmle.label | [ClassInitializedMember,ConstructorDefinition] constructor() {} | @@ -490,14 +569,14 @@ nodes | type_definitions.ts:9:3:9:6 | [FieldDeclaration] x: T | semmle.label | [FieldDeclaration] x: T | | type_definitions.ts:9:6:9:6 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T | | type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.label | [DeclStmt] let c = ... | -| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.order | 64 | +| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.order | 73 | | type_definitions.ts:11:5:11:5 | [VarDecl] c | semmle.label | [VarDecl] c | | type_definitions.ts:11:5:11:16 | [VariableDeclarator] c: C | semmle.label | [VariableDeclarator] c: C | | type_definitions.ts:11:8:11:8 | [LocalTypeAccess] C | semmle.label | [LocalTypeAccess] C | | type_definitions.ts:11:8:11:16 | [GenericTypeExpr] C | semmle.label | [GenericTypeExpr] C | | type_definitions.ts:11:10:11:15 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.label | [EnumDeclaration,TypeDefinition] enum Co ... blue } | -| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.order | 65 | +| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.order | 74 | | type_definitions.ts:13:6:13:10 | [VarDecl] Color | semmle.label | [VarDecl] Color | | type_definitions.ts:14:3:14:5 | [EnumMember,TypeDefinition] red | semmle.label | [EnumMember,TypeDefinition] red | | type_definitions.ts:14:3:14:5 | [VarDecl] red | semmle.label | [VarDecl] red | @@ -506,29 +585,29 @@ nodes | type_definitions.ts:14:15:14:18 | [EnumMember,TypeDefinition] blue | semmle.label | [EnumMember,TypeDefinition] blue | | type_definitions.ts:14:15:14:18 | [VarDecl] blue | semmle.label | [VarDecl] blue | | type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.label | [DeclStmt] let color = ... | -| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.order | 66 | +| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.order | 75 | | type_definitions.ts:16:5:16:9 | [VarDecl] color | semmle.label | [VarDecl] color | | type_definitions.ts:16:5:16:16 | [VariableDeclarator] color: Color | semmle.label | [VariableDeclarator] color: Color | | type_definitions.ts:16:12:16:16 | [LocalTypeAccess] Color | semmle.label | [LocalTypeAccess] Color | | type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.label | [EnumDeclaration,TypeDefinition] enum En ... ember } | -| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.order | 67 | +| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.order | 76 | | type_definitions.ts:18:6:18:22 | [VarDecl] EnumWithOneMember | semmle.label | [VarDecl] EnumWithOneMember | | type_definitions.ts:18:26:18:31 | [EnumMember,TypeDefinition] member | semmle.label | [EnumMember,TypeDefinition] member | | type_definitions.ts:18:26:18:31 | [VarDecl] member | semmle.label | [VarDecl] member | | type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.label | [DeclStmt] let e = ... | -| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.order | 68 | +| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.order | 77 | | type_definitions.ts:19:5:19:5 | [VarDecl] e | semmle.label | [VarDecl] e | | type_definitions.ts:19:5:19:24 | [VariableDeclarator] e: EnumWithOneMember | semmle.label | [VariableDeclarator] e: EnumWithOneMember | | type_definitions.ts:19:8:19:24 | [LocalTypeAccess] EnumWithOneMember | semmle.label | [LocalTypeAccess] EnumWithOneMember | | type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | -| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | semmle.order | 69 | +| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | semmle.order | 78 | | type_definitions.ts:21:6:21:10 | [Identifier] Alias | semmle.label | [Identifier] Alias | | type_definitions.ts:21:12:21:12 | [Identifier] T | semmle.label | [Identifier] T | | type_definitions.ts:21:12:21:12 | [TypeParameter] T | semmle.label | [TypeParameter] T | | type_definitions.ts:21:17:21:17 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T | | type_definitions.ts:21:17:21:19 | [ArrayTypeExpr] T[] | semmle.label | [ArrayTypeExpr] T[] | | type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.label | [DeclStmt] let aliasForNumberArray = ... | -| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.order | 70 | +| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.order | 79 | | type_definitions.ts:22:5:22:23 | [VarDecl] aliasForNumberArray | semmle.label | [VarDecl] aliasForNumberArray | | type_definitions.ts:22:5:22:38 | [VariableDeclarator] aliasFo ... number> | semmle.label | [VariableDeclarator] aliasFo ... number> | | type_definitions.ts:22:26:22:30 | [LocalTypeAccess] Alias | semmle.label | [LocalTypeAccess] Alias | @@ -665,6 +744,34 @@ edges | file://:0:0:0:0 | (TypeParameters) | type_definitions.ts:8:9:8:9 | [TypeParameter] T | semmle.order | 0 | | file://:0:0:0:0 | (TypeParameters) | type_definitions.ts:21:12:21:12 | [TypeParameter] T | semmle.label | 0 | | file://:0:0:0:0 | (TypeParameters) | type_definitions.ts:21:12:21:12 | [TypeParameter] T | semmle.order | 0 | +| middle-rest.ts:1:1:1:40 | [DeclStmt] let foo = ... | middle-rest.ts:1:5:1:39 | [VariableDeclarator] foo: [b ... number] | semmle.label | 1 | +| middle-rest.ts:1:1:1:40 | [DeclStmt] let foo = ... | middle-rest.ts:1:5:1:39 | [VariableDeclarator] foo: [b ... number] | semmle.order | 1 | +| middle-rest.ts:1:5:1:39 | [VariableDeclarator] foo: [b ... number] | middle-rest.ts:1:5:1:7 | [VarDecl] foo | semmle.label | 1 | +| middle-rest.ts:1:5:1:39 | [VariableDeclarator] foo: [b ... number] | middle-rest.ts:1:5:1:7 | [VarDecl] foo | semmle.order | 1 | +| middle-rest.ts:1:5:1:39 | [VariableDeclarator] foo: [b ... number] | middle-rest.ts:1:10:1:39 | [TupleTypeExpr] [boolea ... number] | semmle.label | 2 | +| middle-rest.ts:1:5:1:39 | [VariableDeclarator] foo: [b ... number] | middle-rest.ts:1:10:1:39 | [TupleTypeExpr] [boolea ... number] | semmle.order | 2 | +| middle-rest.ts:1:10:1:39 | [TupleTypeExpr] [boolea ... number] | middle-rest.ts:1:11:1:17 | [KeywordTypeExpr] boolean | semmle.label | 1 | +| middle-rest.ts:1:10:1:39 | [TupleTypeExpr] [boolea ... number] | middle-rest.ts:1:11:1:17 | [KeywordTypeExpr] boolean | semmle.order | 1 | +| middle-rest.ts:1:10:1:39 | [TupleTypeExpr] [boolea ... number] | middle-rest.ts:1:20:1:30 | [RestTypeExpr] ...string[] | semmle.label | 2 | +| middle-rest.ts:1:10:1:39 | [TupleTypeExpr] [boolea ... number] | middle-rest.ts:1:20:1:30 | [RestTypeExpr] ...string[] | semmle.order | 2 | +| middle-rest.ts:1:10:1:39 | [TupleTypeExpr] [boolea ... number] | middle-rest.ts:1:33:1:38 | [KeywordTypeExpr] number | semmle.label | 3 | +| middle-rest.ts:1:10:1:39 | [TupleTypeExpr] [boolea ... number] | middle-rest.ts:1:33:1:38 | [KeywordTypeExpr] number | semmle.order | 3 | +| middle-rest.ts:1:20:1:30 | [RestTypeExpr] ...string[] | middle-rest.ts:1:23:1:30 | [ArrayTypeExpr] string[] | semmle.label | 1 | +| middle-rest.ts:1:20:1:30 | [RestTypeExpr] ...string[] | middle-rest.ts:1:23:1:30 | [ArrayTypeExpr] string[] | semmle.order | 1 | +| middle-rest.ts:1:23:1:30 | [ArrayTypeExpr] string[] | middle-rest.ts:1:23:1:28 | [KeywordTypeExpr] string | semmle.label | 1 | +| middle-rest.ts:1:23:1:30 | [ArrayTypeExpr] string[] | middle-rest.ts:1:23:1:28 | [KeywordTypeExpr] string | semmle.order | 1 | +| middle-rest.ts:3:1:3:26 | [AssignExpr] foo = [ ... ", 123] | middle-rest.ts:3:1:3:3 | [VarRef] foo | semmle.label | 1 | +| middle-rest.ts:3:1:3:26 | [AssignExpr] foo = [ ... ", 123] | middle-rest.ts:3:1:3:3 | [VarRef] foo | semmle.order | 1 | +| middle-rest.ts:3:1:3:26 | [AssignExpr] foo = [ ... ", 123] | middle-rest.ts:3:7:3:26 | [ArrayExpr] [true, "hello", 123] | semmle.label | 2 | +| middle-rest.ts:3:1:3:26 | [AssignExpr] foo = [ ... ", 123] | middle-rest.ts:3:7:3:26 | [ArrayExpr] [true, "hello", 123] | semmle.order | 2 | +| middle-rest.ts:3:1:3:27 | [ExprStmt] foo = [ ... , 123]; | middle-rest.ts:3:1:3:26 | [AssignExpr] foo = [ ... ", 123] | semmle.label | 1 | +| middle-rest.ts:3:1:3:27 | [ExprStmt] foo = [ ... , 123]; | middle-rest.ts:3:1:3:26 | [AssignExpr] foo = [ ... ", 123] | semmle.order | 1 | +| middle-rest.ts:3:7:3:26 | [ArrayExpr] [true, "hello", 123] | middle-rest.ts:3:8:3:11 | [Literal] true | semmle.label | 1 | +| middle-rest.ts:3:7:3:26 | [ArrayExpr] [true, "hello", 123] | middle-rest.ts:3:8:3:11 | [Literal] true | semmle.order | 1 | +| middle-rest.ts:3:7:3:26 | [ArrayExpr] [true, "hello", 123] | middle-rest.ts:3:14:3:20 | [Literal] "hello" | semmle.label | 2 | +| middle-rest.ts:3:7:3:26 | [ArrayExpr] [true, "hello", 123] | middle-rest.ts:3:14:3:20 | [Literal] "hello" | semmle.order | 2 | +| middle-rest.ts:3:7:3:26 | [ArrayExpr] [true, "hello", 123] | middle-rest.ts:3:23:3:25 | [Literal] 123 | semmle.label | 3 | +| middle-rest.ts:3:7:3:26 | [ArrayExpr] [true, "hello", 123] | middle-rest.ts:3:23:3:25 | [Literal] 123 | semmle.order | 3 | | tst.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | tst.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | 1 | | tst.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | tst.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.order | 1 | | tst.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | tst.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | 2 | @@ -1021,6 +1128,100 @@ edges | tst.ts:49:11:49:24 | [VariableDeclarator] b : string = e | tst.ts:49:15:49:20 | [KeywordTypeExpr] string | semmle.order | 2 | | tst.ts:49:11:49:24 | [VariableDeclarator] b : string = e | tst.ts:49:24:49:24 | [VarRef] e | semmle.label | 3 | | tst.ts:49:11:49:24 | [VariableDeclarator] b : string = e | tst.ts:49:24:49:24 | [VarRef] e | semmle.order | 3 | +| tst.ts:54:1:56:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | tst.ts:54:11:54:26 | [Identifier] NonAbstractDummy | semmle.label | 1 | +| tst.ts:54:1:56:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | tst.ts:54:11:54:26 | [Identifier] NonAbstractDummy | semmle.order | 1 | +| tst.ts:54:1:56:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | tst.ts:55:3:55:20 | [MethodSignature] getArea(): number; | semmle.label | 2 | +| tst.ts:54:1:56:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | tst.ts:55:3:55:20 | [MethodSignature] getArea(): number; | semmle.order | 2 | +| tst.ts:55:3:55:20 | [FunctionExpr] getArea(): number; | tst.ts:55:14:55:19 | [KeywordTypeExpr] number | semmle.label | 4 | +| tst.ts:55:3:55:20 | [FunctionExpr] getArea(): number; | tst.ts:55:14:55:19 | [KeywordTypeExpr] number | semmle.order | 4 | +| tst.ts:55:3:55:20 | [MethodSignature] getArea(): number; | tst.ts:55:3:55:9 | [Label] getArea | semmle.label | 1 | +| tst.ts:55:3:55:20 | [MethodSignature] getArea(): number; | tst.ts:55:3:55:9 | [Label] getArea | semmle.order | 1 | +| tst.ts:55:3:55:20 | [MethodSignature] getArea(): number; | tst.ts:55:3:55:20 | [FunctionExpr] getArea(): number; | semmle.label | 2 | +| tst.ts:55:3:55:20 | [MethodSignature] getArea(): number; | tst.ts:55:3:55:20 | [FunctionExpr] getArea(): number; | semmle.order | 2 | +| tst.ts:58:1:60:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | tst.ts:58:11:58:17 | [Identifier] HasArea | semmle.label | 1 | +| tst.ts:58:1:60:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | tst.ts:58:11:58:17 | [Identifier] HasArea | semmle.order | 1 | +| tst.ts:58:1:60:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | tst.ts:59:3:59:20 | [MethodSignature] getArea(): number; | semmle.label | 2 | +| tst.ts:58:1:60:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | tst.ts:59:3:59:20 | [MethodSignature] getArea(): number; | semmle.order | 2 | +| tst.ts:59:3:59:20 | [FunctionExpr] getArea(): number; | tst.ts:59:14:59:19 | [KeywordTypeExpr] number | semmle.label | 4 | +| tst.ts:59:3:59:20 | [FunctionExpr] getArea(): number; | tst.ts:59:14:59:19 | [KeywordTypeExpr] number | semmle.order | 4 | +| tst.ts:59:3:59:20 | [MethodSignature] getArea(): number; | tst.ts:59:3:59:9 | [Label] getArea | semmle.label | 1 | +| tst.ts:59:3:59:20 | [MethodSignature] getArea(): number; | tst.ts:59:3:59:9 | [Label] getArea | semmle.order | 1 | +| tst.ts:59:3:59:20 | [MethodSignature] getArea(): number; | tst.ts:59:3:59:20 | [FunctionExpr] getArea(): number; | semmle.label | 2 | +| tst.ts:59:3:59:20 | [MethodSignature] getArea(): number; | tst.ts:59:3:59:20 | [FunctionExpr] getArea(): number; | semmle.order | 2 | +| tst.ts:63:1:63:45 | [DeclStmt] let Ctor = ... | tst.ts:63:5:63:44 | [VariableDeclarator] Ctor: a ... = Shape | semmle.label | 1 | +| tst.ts:63:1:63:45 | [DeclStmt] let Ctor = ... | tst.ts:63:5:63:44 | [VariableDeclarator] Ctor: a ... = Shape | semmle.order | 1 | +| tst.ts:63:5:63:44 | [VariableDeclarator] Ctor: a ... = Shape | tst.ts:63:5:63:8 | [VarDecl] Ctor | semmle.label | 1 | +| tst.ts:63:5:63:44 | [VariableDeclarator] Ctor: a ... = Shape | tst.ts:63:5:63:8 | [VarDecl] Ctor | semmle.order | 1 | +| tst.ts:63:5:63:44 | [VariableDeclarator] Ctor: a ... = Shape | tst.ts:63:11:63:36 | [FunctionTypeExpr] abstrac ... HasArea | semmle.label | 2 | +| tst.ts:63:5:63:44 | [VariableDeclarator] Ctor: a ... = Shape | tst.ts:63:11:63:36 | [FunctionTypeExpr] abstrac ... HasArea | semmle.order | 2 | +| tst.ts:63:5:63:44 | [VariableDeclarator] Ctor: a ... = Shape | tst.ts:63:40:63:44 | [VarRef] Shape | semmle.label | 3 | +| tst.ts:63:5:63:44 | [VariableDeclarator] Ctor: a ... = Shape | tst.ts:63:40:63:44 | [VarRef] Shape | semmle.order | 3 | +| tst.ts:63:11:63:36 | [FunctionExpr] abstrac ... HasArea | tst.ts:63:30:63:36 | [LocalTypeAccess] HasArea | semmle.label | 4 | +| tst.ts:63:11:63:36 | [FunctionExpr] abstrac ... HasArea | tst.ts:63:30:63:36 | [LocalTypeAccess] HasArea | semmle.order | 4 | +| tst.ts:63:11:63:36 | [FunctionTypeExpr] abstrac ... HasArea | tst.ts:63:11:63:36 | [FunctionExpr] abstrac ... HasArea | semmle.label | 1 | +| tst.ts:63:11:63:36 | [FunctionTypeExpr] abstrac ... HasArea | tst.ts:63:11:63:36 | [FunctionExpr] abstrac ... HasArea | semmle.order | 1 | +| tst.ts:65:1:65:54 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | tst.ts:65:6:65:12 | [Identifier] MyUnion | semmle.label | 1 | +| tst.ts:65:1:65:54 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | tst.ts:65:6:65:12 | [Identifier] MyUnion | semmle.order | 1 | +| tst.ts:65:1:65:54 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | tst.ts:65:16:65:53 | [UnionTypeExpr] {myUnio ... : true} | semmle.label | 2 | +| tst.ts:65:1:65:54 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | tst.ts:65:16:65:53 | [UnionTypeExpr] {myUnio ... : true} | semmle.order | 2 | +| tst.ts:65:16:65:30 | [InterfaceTypeExpr] {myUnion: true} | tst.ts:65:17:65:29 | [FieldDeclaration] myUnion: true | semmle.label | 1 | +| tst.ts:65:16:65:30 | [InterfaceTypeExpr] {myUnion: true} | tst.ts:65:17:65:29 | [FieldDeclaration] myUnion: true | semmle.order | 1 | +| tst.ts:65:16:65:53 | [UnionTypeExpr] {myUnio ... : true} | tst.ts:65:16:65:30 | [InterfaceTypeExpr] {myUnion: true} | semmle.label | 1 | +| tst.ts:65:16:65:53 | [UnionTypeExpr] {myUnio ... : true} | tst.ts:65:16:65:30 | [InterfaceTypeExpr] {myUnion: true} | semmle.order | 1 | +| tst.ts:65:16:65:53 | [UnionTypeExpr] {myUnio ... : true} | tst.ts:65:34:65:53 | [InterfaceTypeExpr] {stillMyUnion: true} | semmle.label | 2 | +| tst.ts:65:16:65:53 | [UnionTypeExpr] {myUnio ... : true} | tst.ts:65:34:65:53 | [InterfaceTypeExpr] {stillMyUnion: true} | semmle.order | 2 | +| tst.ts:65:17:65:29 | [FieldDeclaration] myUnion: true | tst.ts:65:17:65:23 | [Label] myUnion | semmle.label | 1 | +| tst.ts:65:17:65:29 | [FieldDeclaration] myUnion: true | tst.ts:65:17:65:23 | [Label] myUnion | semmle.order | 1 | +| tst.ts:65:17:65:29 | [FieldDeclaration] myUnion: true | tst.ts:65:26:65:29 | [LiteralTypeExpr] true | semmle.label | 2 | +| tst.ts:65:17:65:29 | [FieldDeclaration] myUnion: true | tst.ts:65:26:65:29 | [LiteralTypeExpr] true | semmle.order | 2 | +| tst.ts:65:34:65:53 | [InterfaceTypeExpr] {stillMyUnion: true} | tst.ts:65:35:65:52 | [FieldDeclaration] stillMyUnion: true | semmle.label | 1 | +| tst.ts:65:34:65:53 | [InterfaceTypeExpr] {stillMyUnion: true} | tst.ts:65:35:65:52 | [FieldDeclaration] stillMyUnion: true | semmle.order | 1 | +| tst.ts:65:35:65:52 | [FieldDeclaration] stillMyUnion: true | tst.ts:65:35:65:46 | [Label] stillMyUnion | semmle.label | 1 | +| tst.ts:65:35:65:52 | [FieldDeclaration] stillMyUnion: true | tst.ts:65:35:65:46 | [Label] stillMyUnion | semmle.order | 1 | +| tst.ts:65:35:65:52 | [FieldDeclaration] stillMyUnion: true | tst.ts:65:49:65:52 | [LiteralTypeExpr] true | semmle.label | 2 | +| tst.ts:65:35:65:52 | [FieldDeclaration] stillMyUnion: true | tst.ts:65:49:65:52 | [LiteralTypeExpr] true | semmle.order | 2 | +| tst.ts:66:1:66:38 | [DeclStmt] let union1 = ... | tst.ts:66:5:66:37 | [VariableDeclarator] union1: ... : true} | semmle.label | 1 | +| tst.ts:66:1:66:38 | [DeclStmt] let union1 = ... | tst.ts:66:5:66:37 | [VariableDeclarator] union1: ... : true} | semmle.order | 1 | +| tst.ts:66:5:66:37 | [VariableDeclarator] union1: ... : true} | tst.ts:66:5:66:10 | [VarDecl] union1 | semmle.label | 1 | +| tst.ts:66:5:66:37 | [VariableDeclarator] union1: ... : true} | tst.ts:66:5:66:10 | [VarDecl] union1 | semmle.order | 1 | +| tst.ts:66:5:66:37 | [VariableDeclarator] union1: ... : true} | tst.ts:66:13:66:19 | [LocalTypeAccess] MyUnion | semmle.label | 2 | +| tst.ts:66:5:66:37 | [VariableDeclarator] union1: ... : true} | tst.ts:66:13:66:19 | [LocalTypeAccess] MyUnion | semmle.order | 2 | +| tst.ts:66:5:66:37 | [VariableDeclarator] union1: ... : true} | tst.ts:66:23:66:37 | [ObjectExpr] {myUnion: ...} | semmle.label | 3 | +| tst.ts:66:5:66:37 | [VariableDeclarator] union1: ... : true} | tst.ts:66:23:66:37 | [ObjectExpr] {myUnion: ...} | semmle.order | 3 | +| tst.ts:66:23:66:37 | [ObjectExpr] {myUnion: ...} | tst.ts:66:24:66:36 | [Property] myUnion: true | semmle.label | 1 | +| tst.ts:66:23:66:37 | [ObjectExpr] {myUnion: ...} | tst.ts:66:24:66:36 | [Property] myUnion: true | semmle.order | 1 | +| tst.ts:66:24:66:36 | [Property] myUnion: true | tst.ts:66:24:66:30 | [Label] myUnion | semmle.label | 1 | +| tst.ts:66:24:66:36 | [Property] myUnion: true | tst.ts:66:24:66:30 | [Label] myUnion | semmle.order | 1 | +| tst.ts:66:24:66:36 | [Property] myUnion: true | tst.ts:66:33:66:36 | [Literal] true | semmle.label | 2 | +| tst.ts:66:24:66:36 | [Property] myUnion: true | tst.ts:66:33:66:36 | [Literal] true | semmle.order | 2 | +| tst.ts:68:1:68:49 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | tst.ts:68:6:68:13 | [Identifier] MyUnion2 | semmle.label | 1 | +| tst.ts:68:1:68:49 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | tst.ts:68:6:68:13 | [Identifier] MyUnion2 | semmle.order | 1 | +| tst.ts:68:1:68:49 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | tst.ts:68:17:68:48 | [UnionTypeExpr] MyUnion ... : true} | semmle.label | 2 | +| tst.ts:68:1:68:49 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | tst.ts:68:17:68:48 | [UnionTypeExpr] MyUnion ... : true} | semmle.order | 2 | +| tst.ts:68:17:68:48 | [UnionTypeExpr] MyUnion ... : true} | tst.ts:68:17:68:23 | [LocalTypeAccess] MyUnion | semmle.label | 1 | +| tst.ts:68:17:68:48 | [UnionTypeExpr] MyUnion ... : true} | tst.ts:68:17:68:23 | [LocalTypeAccess] MyUnion | semmle.order | 1 | +| tst.ts:68:17:68:48 | [UnionTypeExpr] MyUnion ... : true} | tst.ts:68:27:68:48 | [InterfaceTypeExpr] {yetAno ... : true} | semmle.label | 2 | +| tst.ts:68:17:68:48 | [UnionTypeExpr] MyUnion ... : true} | tst.ts:68:27:68:48 | [InterfaceTypeExpr] {yetAno ... : true} | semmle.order | 2 | +| tst.ts:68:27:68:48 | [InterfaceTypeExpr] {yetAno ... : true} | tst.ts:68:28:68:47 | [FieldDeclaration] yetAnotherType: true | semmle.label | 1 | +| tst.ts:68:27:68:48 | [InterfaceTypeExpr] {yetAno ... : true} | tst.ts:68:28:68:47 | [FieldDeclaration] yetAnotherType: true | semmle.order | 1 | +| tst.ts:68:28:68:47 | [FieldDeclaration] yetAnotherType: true | tst.ts:68:28:68:41 | [Label] yetAnotherType | semmle.label | 1 | +| tst.ts:68:28:68:47 | [FieldDeclaration] yetAnotherType: true | tst.ts:68:28:68:41 | [Label] yetAnotherType | semmle.order | 1 | +| tst.ts:68:28:68:47 | [FieldDeclaration] yetAnotherType: true | tst.ts:68:44:68:47 | [LiteralTypeExpr] true | semmle.label | 2 | +| tst.ts:68:28:68:47 | [FieldDeclaration] yetAnotherType: true | tst.ts:68:44:68:47 | [LiteralTypeExpr] true | semmle.order | 2 | +| tst.ts:69:1:69:46 | [DeclStmt] let union2 = ... | tst.ts:69:5:69:45 | [VariableDeclarator] union2: ... : true} | semmle.label | 1 | +| tst.ts:69:1:69:46 | [DeclStmt] let union2 = ... | tst.ts:69:5:69:45 | [VariableDeclarator] union2: ... : true} | semmle.order | 1 | +| tst.ts:69:5:69:45 | [VariableDeclarator] union2: ... : true} | tst.ts:69:5:69:10 | [VarDecl] union2 | semmle.label | 1 | +| tst.ts:69:5:69:45 | [VariableDeclarator] union2: ... : true} | tst.ts:69:5:69:10 | [VarDecl] union2 | semmle.order | 1 | +| tst.ts:69:5:69:45 | [VariableDeclarator] union2: ... : true} | tst.ts:69:13:69:20 | [LocalTypeAccess] MyUnion2 | semmle.label | 2 | +| tst.ts:69:5:69:45 | [VariableDeclarator] union2: ... : true} | tst.ts:69:13:69:20 | [LocalTypeAccess] MyUnion2 | semmle.order | 2 | +| tst.ts:69:5:69:45 | [VariableDeclarator] union2: ... : true} | tst.ts:69:24:69:45 | [ObjectExpr] {yetAnotherType: ...} | semmle.label | 3 | +| tst.ts:69:5:69:45 | [VariableDeclarator] union2: ... : true} | tst.ts:69:24:69:45 | [ObjectExpr] {yetAnotherType: ...} | semmle.order | 3 | +| tst.ts:69:24:69:45 | [ObjectExpr] {yetAnotherType: ...} | tst.ts:69:25:69:44 | [Property] yetAnotherType: true | semmle.label | 1 | +| tst.ts:69:24:69:45 | [ObjectExpr] {yetAnotherType: ...} | tst.ts:69:25:69:44 | [Property] yetAnotherType: true | semmle.order | 1 | +| tst.ts:69:25:69:44 | [Property] yetAnotherType: true | tst.ts:69:25:69:38 | [Label] yetAnotherType | semmle.label | 1 | +| tst.ts:69:25:69:44 | [Property] yetAnotherType: true | tst.ts:69:25:69:38 | [Label] yetAnotherType | semmle.order | 1 | +| tst.ts:69:25:69:44 | [Property] yetAnotherType: true | tst.ts:69:41:69:44 | [Literal] true | semmle.label | 2 | +| tst.ts:69:25:69:44 | [Property] yetAnotherType: true | tst.ts:69:41:69:44 | [Literal] true | semmle.order | 2 | | type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | type_alias.ts:1:6:1:6 | [Identifier] B | semmle.label | 1 | | type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | type_alias.ts:1:6:1:6 | [Identifier] B | semmle.order | 1 | | type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | type_alias.ts:1:10:1:16 | [KeywordTypeExpr] boolean | semmle.label | 2 | diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tests.expected b/javascript/ql/test/library-tests/TypeScript/Types/tests.expected index dab0592c334..c9cad8a1443 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/tests.expected +++ b/javascript/ql/test/library-tests/TypeScript/Types/tests.expected @@ -15,6 +15,13 @@ getExprType | boolean-type.ts:15:5:15:12 | boolean6 | boolean | | dummy.ts:2:12:2:12 | x | number | | dummy.ts:2:16:2:16 | 5 | 5 | +| middle-rest.ts:1:5:1:7 | foo | [boolean, ...string[], number] | +| middle-rest.ts:3:1:3:3 | foo | [boolean, ...string[], number] | +| middle-rest.ts:3:1:3:26 | foo = [ ... ", 123] | [true, string, number] | +| middle-rest.ts:3:7:3:26 | [true, "hello", 123] | [boolean, ...string[], number] | +| middle-rest.ts:3:8:3:11 | true | true | +| middle-rest.ts:3:14:3:20 | "hello" | "hello" | +| middle-rest.ts:3:23:3:25 | 123 | 123 | | tst.ts:1:13:1:17 | dummy | typeof library-tests/TypeScript/Types/dummy.ts | | tst.ts:1:24:1:32 | "./dummy" | any | | tst.ts:3:5:3:10 | numVar | number | @@ -100,6 +107,24 @@ getExprType | tst.ts:48:20:48:27 | "string" | "string" | | tst.ts:49:11:49:11 | b | string | | tst.ts:49:24:49:24 | e | string | +| tst.ts:55:3:55:9 | getArea | () => number | +| tst.ts:55:3:55:20 | getArea(): number; | () => number | +| tst.ts:59:3:59:9 | getArea | () => number | +| tst.ts:59:3:59:20 | getArea(): number; | () => number | +| tst.ts:63:5:63:8 | Ctor | abstract new () => HasArea | +| tst.ts:63:11:63:36 | abstrac ... HasArea | abstract new () => HasArea | +| tst.ts:63:40:63:44 | Shape | any | +| tst.ts:65:17:65:23 | myUnion | true | +| tst.ts:65:35:65:46 | stillMyUnion | true | +| tst.ts:66:5:66:10 | union1 | MyUnion | +| tst.ts:66:23:66:37 | {myUnion: true} | MyUnion | +| tst.ts:66:24:66:30 | myUnion | true | +| tst.ts:66:33:66:36 | true | true | +| tst.ts:68:28:68:41 | yetAnotherType | true | +| tst.ts:69:5:69:10 | union2 | MyUnion2 | +| tst.ts:69:24:69:45 | {yetAno ... : true} | MyUnion2 | +| tst.ts:69:25:69:38 | yetAnotherType | true | +| tst.ts:69:41:69:44 | true | true | | type_alias.ts:3:5:3:5 | b | boolean | | type_alias.ts:7:5:7:5 | c | ValueOrArray | | type_alias.ts:14:9:14:32 | [proper ... ]: Json | any | @@ -149,6 +174,10 @@ getExprType | type_definitions.ts:19:5:19:5 | e | EnumWithOneMember | | type_definitions.ts:22:5:22:23 | aliasForNumberArray | Alias | getTypeDefinitionType +| tst.ts:54:1:56:1 | interfa ... mber;\\n} | NonAbstractDummy | +| tst.ts:58:1:60:1 | interfa ... mber;\\n} | HasArea | +| tst.ts:65:1:65:54 | type My ... true}; | MyUnion | +| tst.ts:68:1:68:49 | type My ... true}; | MyUnion2 | | type_alias.ts:1:1:1:17 | type B = boolean; | boolean | | type_alias.ts:5:1:5:50 | type Va ... ay>; | ValueOrArray | | type_alias.ts:9:1:15:13 | type Js ... Json[]; | Json | @@ -185,6 +214,12 @@ getTypeExprType | boolean-type.ts:15:15:15:19 | false | false | | boolean-type.ts:15:15:15:29 | false \| boolean | boolean | | boolean-type.ts:15:23:15:29 | boolean | boolean | +| middle-rest.ts:1:10:1:39 | [boolea ... number] | [boolean, ...string[], number] | +| middle-rest.ts:1:11:1:17 | boolean | boolean | +| middle-rest.ts:1:20:1:30 | ...string[] | string | +| middle-rest.ts:1:23:1:28 | string | string | +| middle-rest.ts:1:23:1:30 | string[] | string[] | +| middle-rest.ts:1:33:1:38 | number | number | | tst.ts:3:13:3:18 | number | number | | tst.ts:9:13:9:18 | string | string | | tst.ts:14:20:14:25 | string | string | @@ -232,6 +267,25 @@ getTypeExprType | tst.ts:39:60:39:67 | number[] | number[] | | tst.ts:40:18:40:24 | unknown | unknown | | tst.ts:49:15:49:20 | string | string | +| tst.ts:54:11:54:26 | NonAbstractDummy | NonAbstractDummy | +| tst.ts:55:14:55:19 | number | number | +| tst.ts:58:11:58:17 | HasArea | HasArea | +| tst.ts:59:14:59:19 | number | number | +| tst.ts:63:11:63:36 | abstrac ... HasArea | abstract new () => HasArea | +| tst.ts:63:30:63:36 | HasArea | HasArea | +| tst.ts:65:6:65:12 | MyUnion | MyUnion | +| tst.ts:65:16:65:30 | {myUnion: true} | { myUnion: true; } | +| tst.ts:65:16:65:53 | {myUnio ... : true} | { myUnion: true; } \| { stillMyUnion: true; } | +| tst.ts:65:26:65:29 | true | true | +| tst.ts:65:34:65:53 | {stillMyUnion: true} | { stillMyUnion: true; } | +| tst.ts:65:49:65:52 | true | true | +| tst.ts:66:13:66:19 | MyUnion | MyUnion | +| tst.ts:68:6:68:13 | MyUnion2 | MyUnion2 | +| tst.ts:68:17:68:23 | MyUnion | MyUnion | +| tst.ts:68:17:68:48 | MyUnion ... : true} | MyUnion \| { yetAnotherType: true; } | +| tst.ts:68:27:68:48 | {yetAno ... : true} | { yetAnotherType: true; } | +| tst.ts:68:44:68:47 | true | true | +| tst.ts:69:13:69:20 | MyUnion2 | MyUnion2 | | type_alias.ts:1:6:1:6 | B | boolean | | type_alias.ts:1:10:1:16 | boolean | boolean | | type_alias.ts:3:8:3:8 | B | boolean | @@ -304,13 +358,29 @@ referenceDefinition | Color.red | type_definitions.ts:14:3:14:5 | red | | E | type_definition_objects.ts:6:8:6:16 | enum E {} | | EnumWithOneMember | type_definitions.ts:18:26:18:31 | member | +| HasArea | tst.ts:58:1:60:1 | interfa ... mber;\\n} | | I | type_definitions.ts:3:1:5:1 | interfa ... x: S;\\n} | | I | type_definitions.ts:3:1:5:1 | interfa ... x: S;\\n} | | Json | type_alias.ts:9:1:15:13 | type Js ... Json[]; | +| MyUnion | tst.ts:65:1:65:54 | type My ... true}; | +| MyUnion2 | tst.ts:68:1:68:49 | type My ... true}; | +| NonAbstractDummy | tst.ts:54:1:56:1 | interfa ... mber;\\n} | | ValueOrArray | type_alias.ts:5:1:5:50 | type Va ... ay>; | | ValueOrArray | type_alias.ts:5:1:5:50 | type Va ... ay>; | | VirtualNode | type_alias.ts:19:1:21:57 | type Vi ... ode[]]; | tupleTypes +| middle-rest.ts:1:5:1:7 | foo | [boolean, ...string[], number] | 0 | boolean | 2 | string | +| middle-rest.ts:1:5:1:7 | foo | [boolean, ...string[], number] | 1 | string | 2 | string | +| middle-rest.ts:1:5:1:7 | foo | [boolean, ...string[], number] | 2 | number | 2 | string | +| middle-rest.ts:3:1:3:3 | foo | [boolean, ...string[], number] | 0 | boolean | 2 | string | +| middle-rest.ts:3:1:3:3 | foo | [boolean, ...string[], number] | 1 | string | 2 | string | +| middle-rest.ts:3:1:3:3 | foo | [boolean, ...string[], number] | 2 | number | 2 | string | +| middle-rest.ts:3:1:3:26 | foo = [ ... ", 123] | [true, string, number] | 0 | true | 3 | no-rest | +| middle-rest.ts:3:1:3:26 | foo = [ ... ", 123] | [true, string, number] | 1 | string | 3 | no-rest | +| middle-rest.ts:3:1:3:26 | foo = [ ... ", 123] | [true, string, number] | 2 | number | 3 | no-rest | +| middle-rest.ts:3:7:3:26 | [true, "hello", 123] | [boolean, ...string[], number] | 0 | boolean | 2 | string | +| middle-rest.ts:3:7:3:26 | [true, "hello", 123] | [boolean, ...string[], number] | 1 | string | 2 | string | +| middle-rest.ts:3:7:3:26 | [true, "hello", 123] | [boolean, ...string[], number] | 2 | number | 2 | string | | tst.ts:34:5:34:9 | tuple | [number, string] | 0 | number | 2 | no-rest | | tst.ts:34:5:34:9 | tuple | [number, string] | 1 | string | 2 | no-rest | | tst.ts:36:5:36:28 | tupleWi ... Element | [number, string, number?] | 0 | number | 2 | no-rest | @@ -331,3 +401,50 @@ unknownType | tst.ts:40:5:40:15 | unknownType | unknown | | tst.ts:47:8:47:8 | e | unknown | | tst.ts:48:14:48:14 | e | unknown | +abstractSignature +| (): HasArea | +| new (): HasArea | +unionIndex +| 1 | 0 | 1 \| 2 | +| 2 | 1 | 1 \| 2 | +| "bigint" | 2 | "string" \| "number" \| "bigint" \| "boolean" \| "s... | +| "boolean" | 3 | "string" \| "number" \| "bigint" \| "boolean" \| "s... | +| "function" | 7 | "string" \| "number" \| "bigint" \| "boolean" \| "s... | +| "number" | 1 | "string" \| "number" \| "bigint" \| "boolean" \| "s... | +| "object" | 6 | "string" \| "number" \| "bigint" \| "boolean" \| "s... | +| "string" | 0 | "string" \| "number" \| "bigint" \| "boolean" \| "s... | +| "symbol" | 4 | "string" \| "number" \| "bigint" \| "boolean" \| "s... | +| "undefined" | 5 | "string" \| "number" \| "bigint" \| "boolean" \| "s... | +| Json[] | 5 | string \| number \| boolean \| { [property: string... | +| T | 0 | T \| ValueOrArray[] | +| ValueOrArray[] | 1 | T \| ValueOrArray[] | +| ValueOrArray[] | 1 | number \| ValueOrArray[] | +| [string, { [key: string]: any; }, ...VirtualNod... | 1 | VirtualNode \| { [key: string]: any; } | +| [string, { [key: string]: any; }, ...VirtualNod... | 1 | string \| [string, { [key: string]: any; }, ...V... | +| false | 0 | boolean | +| false | 2 | string \| number \| boolean | +| false | 2 | string \| number \| boolean \| { [property: string... | +| number | 0 | number \| ValueOrArray[] | +| number | 1 | string \| number | +| number | 1 | string \| number \| boolean | +| number | 1 | string \| number \| boolean \| { [property: string... | +| number | 1 | string \| number \| true | +| string | 0 | VirtualNode \| { [key: string]: any; } | +| string | 0 | string \| [string, { [key: string]: any; }, ...V... | +| string | 0 | string \| number | +| string | 0 | string \| number \| boolean | +| string | 0 | string \| number \| boolean \| { [property: string... | +| string | 0 | string \| number \| true | +| string | 0 | string \| { [key: string]: any; } | +| true | 1 | boolean | +| true | 2 | string \| number \| true | +| true | 3 | string \| number \| boolean | +| true | 3 | string \| number \| boolean \| { [property: string... | +| { [key: string]: any; } | 1 | string \| { [key: string]: any; } | +| { [key: string]: any; } | 2 | VirtualNode \| { [key: string]: any; } | +| { [property: string]: Json; } | 4 | string \| number \| boolean \| { [property: string... | +| { myUnion: true; } | 0 | MyUnion \| { yetAnotherType: true; } | +| { myUnion: true; } | 0 | { myUnion: true; } \| { stillMyUnion: true; } | +| { stillMyUnion: true; } | 1 | MyUnion \| { yetAnotherType: true; } | +| { stillMyUnion: true; } | 1 | { myUnion: true; } \| { stillMyUnion: true; } | +| { yetAnotherType: true; } | 2 | MyUnion \| { yetAnotherType: true; } | diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tests.ql b/javascript/ql/test/library-tests/TypeScript/Types/tests.ql index e5f86c059e5..0f31295ce50 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/tests.ql +++ b/javascript/ql/test/library-tests/TypeScript/Types/tests.ql @@ -35,3 +35,7 @@ query predicate unknownType(Expr e, Type type) { type = e.getType() and e.getType() instanceof UnknownType } + +query CallSignatureType abstractSignature() { result.isAbstract() } + +query UnionType unionIndex(Type element, int i) { result.getElementType(i) = element } diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tst.ts b/javascript/ql/test/library-tests/TypeScript/Types/tst.ts index 04968386c99..68c4ca6ebdd 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/tst.ts +++ b/javascript/ql/test/library-tests/TypeScript/Types/tst.ts @@ -48,4 +48,22 @@ catch (e: unknown) { if (typeof e === "string") { let b : string = e; } -} \ No newline at end of file +} + + +interface NonAbstractDummy { + getArea(): number; +} + +interface HasArea { + getArea(): number; +} + +// abstract construct signature! +let Ctor: abstract new () => HasArea = Shape; + +type MyUnion = {myUnion: true} | {stillMyUnion: true}; +let union1: MyUnion = {myUnion: true}; + +type MyUnion2 = MyUnion | {yetAnotherType: true}; +let union2: MyUnion2 = {yetAnotherType: true}; \ No newline at end of file diff --git a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected index 47c340f7a8e..2bf2d305cb0 100644 --- a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected +++ b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected @@ -76,6 +76,13 @@ test_ClientRequest | tst.js:229:5:229:67 | needle( ... ptions) | | tst.js:231:5:233:6 | needle. ... \\n }) | | tst.js:235:5:237:6 | needle. ... \\n }) | +| tst.js:247:24:247:68 | request ... o.png') | +| tst.js:249:1:251:2 | form.su ... e();\\n}) | +| tst.js:257:1:262:2 | form.su ... rs()\\n}) | +| tst.js:267:1:267:61 | httpPro ... 9000'}) | +| tst.js:269:13:269:48 | httpPro ... ptions) | +| tst.js:271:3:271:61 | proxy.w ... 080' }) | +| tst.js:274:1:283:2 | httpPro ... true\\n}) | test_getADataNode | tst.js:53:5:53:23 | axios({data: data}) | tst.js:53:18:53:21 | data | | tst.js:57:5:57:39 | axios.p ... data2}) | tst.js:57:19:57:23 | data1 | @@ -110,12 +117,18 @@ test_getADataNode | tst.js:229:5:229:67 | needle( ... ptions) | tst.js:229:50:229:57 | "MyData" | | tst.js:235:5:237:6 | needle. ... \\n }) | tst.js:228:32:228:70 | { 'X-Cu ... tuna' } | | tst.js:235:5:237:6 | needle. ... \\n }) | tst.js:235:44:235:49 | "data" | +| tst.js:249:1:251:2 | form.su ... e();\\n}) | tst.js:245:25:245:34 | 'my value' | +| tst.js:249:1:251:2 | form.su ... e();\\n}) | tst.js:246:26:246:43 | Buffer.from("foo") | +| tst.js:249:1:251:2 | form.su ... e();\\n}) | tst.js:247:24:247:68 | request ... o.png') | +| tst.js:257:1:262:2 | form.su ... rs()\\n}) | tst.js:255:25:255:35 | 'new_value' | test_getHost | tst.js:87:5:87:39 | http.ge ... host}) | tst.js:87:34:87:37 | host | | tst.js:89:5:89:23 | axios({host: host}) | tst.js:89:18:89:21 | host | | tst.js:91:5:91:34 | got(rel ... host}) | tst.js:91:29:91:32 | host | | tst.js:93:5:93:35 | net.req ... host }) | tst.js:93:29:93:32 | host | | tst.js:219:5:219:41 | data.so ... Host"}) | tst.js:219:32:219:39 | "myHost" | +| tst.js:257:1:262:2 | form.su ... rs()\\n}) | tst.js:259:11:259:23 | 'example.org' | +| tst.js:274:1:283:2 | httpPro ... true\\n}) | tst.js:277:15:277:30 | 'my-domain-name' | test_getUrl | apollo.js:5:18:5:78 | new cre ... hql' }) | apollo.js:5:44:5:75 | 'https: ... raphql' | | apollo.js:10:1:10:54 | new Htt ... hql' }) | apollo.js:10:21:10:51 | 'http:/ ... raphql' | @@ -199,6 +212,12 @@ test_getUrl | tst.js:229:5:229:67 | needle( ... ptions) | tst.js:229:20:229:47 | "http:/ ... oo/bar" | | tst.js:231:5:233:6 | needle. ... \\n }) | tst.js:231:16:231:35 | "http://example.org" | | tst.js:235:5:237:6 | needle. ... \\n }) | tst.js:235:17:235:41 | "http:/ ... g/post" | +| tst.js:247:24:247:68 | request ... o.png') | tst.js:247:32:247:67 | 'http:/ ... go.png' | +| tst.js:249:1:251:2 | form.su ... e();\\n}) | tst.js:249:13:249:33 | 'http:/ ... e.org/' | +| tst.js:257:1:262:2 | form.su ... rs()\\n}) | tst.js:257:13:262:1 | {\\n m ... ers()\\n} | +| tst.js:267:1:267:61 | httpPro ... 9000'}) | tst.js:267:37:267:59 | 'http:/ ... t:9000' | +| tst.js:271:3:271:61 | proxy.w ... 080' }) | tst.js:271:33:271:58 | 'http:/ ... m:8080' | +| tst.js:274:1:283:2 | httpPro ... true\\n}) | tst.js:275:13:281:5 | {\\n ... ,\\n } | test_getAResponseDataNode | tst.js:19:5:19:23 | requestPromise(url) | tst.js:19:5:19:23 | requestPromise(url) | text | true | | tst.js:21:5:21:23 | superagent.get(url) | tst.js:21:5:21:23 | superagent.get(url) | stream | true | diff --git a/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js b/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js index a24a0dca791..4003fd1b0a3 100644 --- a/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js +++ b/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js @@ -235,4 +235,49 @@ const needle = require("needle"); needle.post("http://example.org/post", "data", options, (err, resp, body) => { }); -})(); \ No newline at end of file +})(); + +var FormData = require('form-data'); +var request = require('request'); + +var form = new FormData(); + +form.append('my_field', 'my value'); +form.append('my_buffer', Buffer.from("foo")); +form.append('my_logo', request('http://example.org/images/logo.png')); + +form.submit('http://example.org/', (err, res) => { + res.resume(); +}); + + +var form = new FormData(); +form.append('new_form', 'new_value'); + +form.submit({ + method: 'post', + host: 'example.org', + path: '/upload', + headers: form.getHeaders() +}); + +var httpProxy = require('http-proxy'); +var http = require("http"); + +httpProxy.createProxyServer({target:'http://localhost:9000'}).listen(8000); + +var proxy = httpProxy.createProxyServer(options); +http.createServer(function(req, res) { + proxy.web(req, res, { target: 'http://mytarget.com:8080' }); +}); + +httpProxy.createProxyServer({ + target: { + protocol: 'https:', + host: 'my-domain-name', + port: 443, + pfx: fs.readFileSync('path/to/certificate.p12'), + passphrase: 'password', + }, + changeOrigin: true +}).listen(8000); \ No newline at end of file diff --git a/javascript/ql/test/library-tests/frameworks/NodeJSLib/src/http.js b/javascript/ql/test/library-tests/frameworks/NodeJSLib/src/http.js index 12dc11efcaf..c5fe90fe571 100644 --- a/javascript/ql/test/library-tests/frameworks/NodeJSLib/src/http.js +++ b/javascript/ql/test/library-tests/frameworks/NodeJSLib/src/http.js @@ -73,4 +73,14 @@ http.createServer(function (req, res) { req.on("data", chunk => { // RemoteFlowSource res.send(chunk); }) +}); + +var httpProxy = require('http-proxy'); +var proxy = httpProxy.createProxyServer({}); + +proxy.on('proxyReq', function(proxyReq, req, res, options) { + req.on("data", chunk => { // RemoteFlowSource + res.send(chunk); + }); + res.end("bla"); }); \ No newline at end of file diff --git a/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected b/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected index c80b0059cb6..7835e0280ef 100644 --- a/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected +++ b/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected @@ -56,6 +56,9 @@ test_ResponseExpr | src/http.js:68:17:68:19 | res | src/http.js:68:12:68:27 | (req,res) => f() | | src/http.js:72:34:72:36 | res | src/http.js:72:19:76:1 | functio ... \\n })\\n} | | src/http.js:74:5:74:7 | res | src/http.js:72:19:76:1 | functio ... \\n })\\n} | +| src/http.js:81:46:81:48 | res | src/http.js:81:22:86:1 | functio ... la");\\n} | +| src/http.js:83:5:83:7 | res | src/http.js:81:22:86:1 | functio ... la");\\n} | +| src/http.js:85:3:85:5 | res | src/http.js:81:22:86:1 | functio ... la");\\n} | | src/https.js:4:47:4:49 | res | src/https.js:4:33:10:1 | functio ... .foo;\\n} | | src/https.js:7:3:7:5 | res | src/https.js:4:33:10:1 | functio ... .foo;\\n} | | src/https.js:12:34:12:36 | res | src/https.js:12:20:16:1 | functio ... ar");\\n} | @@ -150,6 +153,9 @@ test_RouteHandler_getAResponseExpr | src/http.js:68:12:68:27 | (req,res) => f() | src/http.js:68:17:68:19 | res | | src/http.js:72:19:76:1 | functio ... \\n })\\n} | src/http.js:72:34:72:36 | res | | src/http.js:72:19:76:1 | functio ... \\n })\\n} | src/http.js:74:5:74:7 | res | +| src/http.js:81:22:86:1 | functio ... la");\\n} | src/http.js:81:46:81:48 | res | +| src/http.js:81:22:86:1 | functio ... la");\\n} | src/http.js:83:5:83:7 | res | +| src/http.js:81:22:86:1 | functio ... la");\\n} | src/http.js:85:3:85:5 | res | | src/https.js:4:33:10:1 | functio ... .foo;\\n} | src/https.js:4:47:4:49 | res | | src/https.js:4:33:10:1 | functio ... .foo;\\n} | src/https.js:7:3:7:5 | res | | src/https.js:12:20:16:1 | functio ... ar");\\n} | src/https.js:12:34:12:36 | res | @@ -189,6 +195,7 @@ test_ResponseSendArgument | src/http.js:14:13:14:17 | "foo" | src/http.js:12:19:16:1 | functio ... ar");\\n} | | src/http.js:15:11:15:15 | "bar" | src/http.js:12:19:16:1 | functio ... ar");\\n} | | src/http.js:64:11:64:16 | "bar2" | src/http.js:62:19:65:1 | functio ... r2");\\n} | +| src/http.js:85:11:85:15 | "bla" | src/http.js:81:22:86:1 | functio ... la");\\n} | | src/https.js:14:13:14:17 | "foo" | src/https.js:12:20:16:1 | functio ... ar");\\n} | | src/https.js:15:11:15:15 | "bar" | src/https.js:12:20:16:1 | functio ... ar");\\n} | | src/indirect.js:26:13:26:17 | "foo" | src/indirect.js:25:24:27:3 | (req, r ... ");\\n } | @@ -235,6 +242,7 @@ test_RemoteFlowSources | src/http.js:40:23:40:30 | authInfo | | src/http.js:45:23:45:27 | error | | src/http.js:73:18:73:22 | chunk | +| src/http.js:82:18:82:22 | chunk | | src/https.js:6:26:6:32 | req.url | | src/https.js:8:3:8:20 | req.headers.cookie | | src/https.js:9:3:9:17 | req.headers.foo | @@ -273,6 +281,8 @@ test_RequestExpr | src/http.js:68:13:68:15 | req | src/http.js:68:12:68:27 | (req,res) => f() | | src/http.js:72:29:72:31 | req | src/http.js:72:19:76:1 | functio ... \\n })\\n} | | src/http.js:73:3:73:5 | req | src/http.js:72:19:76:1 | functio ... \\n })\\n} | +| src/http.js:81:41:81:43 | req | src/http.js:81:22:86:1 | functio ... la");\\n} | +| src/http.js:82:3:82:5 | req | src/http.js:81:22:86:1 | functio ... la");\\n} | | src/https.js:4:42:4:44 | req | src/https.js:4:33:10:1 | functio ... .foo;\\n} | | src/https.js:6:26:6:28 | req | src/https.js:4:33:10:1 | functio ... .foo;\\n} | | src/https.js:8:3:8:5 | req | src/https.js:4:33:10:1 | functio ... .foo;\\n} | @@ -312,6 +322,8 @@ test_RouteHandler_getARequestExpr | src/http.js:68:12:68:27 | (req,res) => f() | src/http.js:68:13:68:15 | req | | src/http.js:72:19:76:1 | functio ... \\n })\\n} | src/http.js:72:29:72:31 | req | | src/http.js:72:19:76:1 | functio ... \\n })\\n} | src/http.js:73:3:73:5 | req | +| src/http.js:81:22:86:1 | functio ... la");\\n} | src/http.js:81:41:81:43 | req | +| src/http.js:81:22:86:1 | functio ... la");\\n} | src/http.js:82:3:82:5 | req | | src/https.js:4:33:10:1 | functio ... .foo;\\n} | src/https.js:4:42:4:44 | req | | src/https.js:4:33:10:1 | functio ... .foo;\\n} | src/https.js:6:26:6:28 | req | | src/https.js:4:33:10:1 | functio ... .foo;\\n} | src/https.js:8:3:8:5 | req | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index 8452d81ee07..cb7c526af5d 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -24,6 +24,9 @@ | highlight.js:38:54:38:59 | [^()]* | Strings starting with 'A((' and with many repetitions of ''' can start matching anywhere after the start of the preceeding [^()]* | | highlight.js:38:64:38:69 | [^()]* | Strings starting with 'A(' and with many repetitions of ''' can start matching anywhere after the start of the preceeding [^()]* | | highlight.js:39:22:39:24 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding [a-zA-Z_]\\w*\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{ | +| jsonschema.js:5:15:5:21 | (a?a?)* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a?a?)*b | +| jsonschema.js:15:23:15:29 | (a?a?)* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a?a?)*b | +| jsonschema.js:20:18:20:24 | (a?a?)* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a?a?)*b | | lib/closure.js:4:6:4:7 | u* | Strings with many repetitions of 'u' can start matching anywhere after the start of the preceeding u*o | | lib/lib.js:1:15:1:16 | a* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding a*b | | lib/lib.js:8:3:8:4 | f* | Strings with many repetitions of 'f' can start matching anywhere after the start of the preceeding f*g | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index a3aa59d63b1..4229d8f0c5f 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -12,6 +12,9 @@ | highlight.js:30:13:30:25 | (?:\\\\.\|[^`])+ | This part of the regular expression may cause exponential backtracking on strings starting with '`' and containing many repetitions of '\\\\_'. | | highlight.js:34:25:34:27 | \\w* | This part of the regular expression may cause exponential backtracking on strings starting with '?A' and containing many repetitions of 'A'. | | highlight.js:38:35:38:40 | [^()]* | This part of the regular expression may cause exponential backtracking on strings starting with 'A((' and containing many repetitions of '')('. | +| jsonschema.js:5:15:5:21 | (a?a?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | +| jsonschema.js:15:23:15:29 | (a?a?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | +| jsonschema.js:20:18:20:24 | (a?a?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | polynomial-redos.js:17:5:17:6 | .* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of ','. | | polynomial-redos.js:41:52:41:63 | [\\x21-\\x7E]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '?'. | | polynomial-redos.js:46:33:46:45 | [a-zA-Z_0-9]* | This part of the regular expression may cause exponential backtracking on strings starting with 'A' and containing many repetitions of 'A'. | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/jsonschema.js b/javascript/ql/test/query-tests/Performance/ReDoS/jsonschema.js new file mode 100644 index 00000000000..542145de484 --- /dev/null +++ b/javascript/ql/test/query-tests/Performance/ReDoS/jsonschema.js @@ -0,0 +1,26 @@ +import Ajv from 'ajv'; + +let thing = { + type: 'string', + pattern: '(a?a?)*b' // NOT OK +} +new Ajv().addSchema(thing, 'thing'); + +export default { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + foo: { + type: "string", + pattern: "(a?a?)*b" // NOT OK + }, + bar: { + type: "object", + patternProperties: { + "(a?a?)*b": { // NOT OK + type: "number" + } + } + } + } +}; diff --git a/javascript/ql/test/query-tests/Security/CWE-079/ExceptionXss/ExceptionXss.expected b/javascript/ql/test/query-tests/Security/CWE-079/ExceptionXss/ExceptionXss.expected index aba89bbe379..f7312726786 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/ExceptionXss/ExceptionXss.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/ExceptionXss/ExceptionXss.expected @@ -1,4 +1,7 @@ nodes +| ajv.js:11:18:11:33 | ajv.errorsText() | +| ajv.js:11:18:11:33 | ajv.errorsText() | +| ajv.js:11:18:11:33 | ajv.errorsText() | | exception-xss.js:2:6:2:28 | foo | | exception-xss.js:2:12:2:28 | document.location | | exception-xss.js:2:12:2:28 | document.location | @@ -87,6 +90,7 @@ nodes | exception-xss.js:182:19:182:23 | error | | exception-xss.js:182:19:182:23 | error | edges +| ajv.js:11:18:11:33 | ajv.errorsText() | ajv.js:11:18:11:33 | ajv.errorsText() | | exception-xss.js:2:6:2:28 | foo | exception-xss.js:9:11:9:13 | foo | | exception-xss.js:2:6:2:28 | foo | exception-xss.js:15:9:15:11 | foo | | exception-xss.js:2:6:2:28 | foo | exception-xss.js:21:11:21:13 | foo | @@ -169,6 +173,7 @@ edges | exception-xss.js:180:26:180:30 | error | exception-xss.js:182:19:182:23 | error | | exception-xss.js:180:26:180:30 | error | exception-xss.js:182:19:182:23 | error | #select +| ajv.js:11:18:11:33 | ajv.errorsText() | ajv.js:11:18:11:33 | ajv.errorsText() | ajv.js:11:18:11:33 | ajv.errorsText() | $@ is reinterpreted as HTML without escaping meta-characters. | ajv.js:11:18:11:33 | ajv.errorsText() | JSON schema validation error | | exception-xss.js:11:18:11:18 | e | exception-xss.js:2:12:2:28 | document.location | exception-xss.js:11:18:11:18 | e | $@ is reinterpreted as HTML without escaping meta-characters. | exception-xss.js:2:12:2:28 | document.location | Exception text | | exception-xss.js:17:18:17:18 | e | exception-xss.js:2:12:2:28 | document.location | exception-xss.js:17:18:17:18 | e | $@ is reinterpreted as HTML without escaping meta-characters. | exception-xss.js:2:12:2:28 | document.location | Exception text | | exception-xss.js:23:18:23:18 | e | exception-xss.js:2:12:2:28 | document.location | exception-xss.js:23:18:23:18 | e | $@ is reinterpreted as HTML without escaping meta-characters. | exception-xss.js:2:12:2:28 | document.location | Exception text | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/ExceptionXss/ajv.js b/javascript/ql/test/query-tests/Security/CWE-079/ExceptionXss/ajv.js new file mode 100644 index 00000000000..2ebbc46a4b3 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-079/ExceptionXss/ajv.js @@ -0,0 +1,13 @@ +import express from 'express'; +import Ajv from 'ajv'; + +let app = express(); +let ajv = new Ajv(); + +ajv.addSchema({type: 'object', additionalProperties: {type: 'number'}}, 'pollData'); + +app.post('/polldata', (req, res) => { + if (!ajv.validate('pollData', req.body)) { + res.send(ajv.errorsText()); // NOT OK + } +}); diff --git a/javascript/ql/test/query-tests/Security/CWE-089/untyped/DatabaseAccesses.expected b/javascript/ql/test/query-tests/Security/CWE-089/untyped/DatabaseAccesses.expected index d17ff8d1cc4..5bf367a4c18 100644 --- a/javascript/ql/test/query-tests/Security/CWE-089/untyped/DatabaseAccesses.expected +++ b/javascript/ql/test/query-tests/Security/CWE-089/untyped/DatabaseAccesses.expected @@ -1,3 +1,7 @@ +| json-schema-validator.js:27:13:27:27 | doc.find(query) | +| json-schema-validator.js:30:13:30:27 | doc.find(query) | +| json-schema-validator.js:33:13:33:27 | doc.find(query) | +| json-schema-validator.js:35:9:35:23 | doc.find(query) | | marsdb-flow-to.js:14:3:14:22 | db.myDoc.find(query) | | marsdb.js:16:3:16:17 | doc.find(query) | | minimongo.js:18:3:18:17 | doc.find(query) | diff --git a/javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected b/javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected index e33f30d01ba..427e2fb853c 100644 --- a/javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected @@ -1,4 +1,12 @@ nodes +| json-schema-validator.js:25:15:25:48 | query | +| json-schema-validator.js:25:23:25:48 | JSON.pa ... y.data) | +| json-schema-validator.js:25:34:25:47 | req.query.data | +| json-schema-validator.js:25:34:25:47 | req.query.data | +| json-schema-validator.js:33:22:33:26 | query | +| json-schema-validator.js:33:22:33:26 | query | +| json-schema-validator.js:35:18:35:22 | query | +| json-schema-validator.js:35:18:35:22 | query | | marsdb-flow-to.js:10:9:10:18 | query | | marsdb-flow-to.js:10:17:10:18 | {} | | marsdb-flow-to.js:11:17:11:24 | req.body | @@ -250,6 +258,13 @@ nodes | tst.js:10:46:10:58 | req.params.id | | tst.js:10:46:10:58 | req.params.id | edges +| json-schema-validator.js:25:15:25:48 | query | json-schema-validator.js:33:22:33:26 | query | +| json-schema-validator.js:25:15:25:48 | query | json-schema-validator.js:33:22:33:26 | query | +| json-schema-validator.js:25:15:25:48 | query | json-schema-validator.js:35:18:35:22 | query | +| json-schema-validator.js:25:15:25:48 | query | json-schema-validator.js:35:18:35:22 | query | +| json-schema-validator.js:25:23:25:48 | JSON.pa ... y.data) | json-schema-validator.js:25:15:25:48 | query | +| json-schema-validator.js:25:34:25:47 | req.query.data | json-schema-validator.js:25:23:25:48 | JSON.pa ... y.data) | +| json-schema-validator.js:25:34:25:47 | req.query.data | json-schema-validator.js:25:23:25:48 | JSON.pa ... y.data) | | marsdb-flow-to.js:10:9:10:18 | query | marsdb-flow-to.js:14:17:14:21 | query | | marsdb-flow-to.js:10:9:10:18 | query | marsdb-flow-to.js:14:17:14:21 | query | | marsdb-flow-to.js:10:17:10:18 | {} | marsdb-flow-to.js:10:9:10:18 | query | @@ -586,6 +601,8 @@ edges | tst.js:10:46:10:58 | req.params.id | tst.js:10:10:10:64 | 'SELECT ... d + '"' | | tst.js:10:46:10:58 | req.params.id | tst.js:10:10:10:64 | 'SELECT ... d + '"' | #select +| json-schema-validator.js:33:22:33:26 | query | json-schema-validator.js:25:34:25:47 | req.query.data | json-schema-validator.js:33:22:33:26 | query | This query depends on $@. | json-schema-validator.js:25:34:25:47 | req.query.data | a user-provided value | +| json-schema-validator.js:35:18:35:22 | query | json-schema-validator.js:25:34:25:47 | req.query.data | json-schema-validator.js:35:18:35:22 | query | This query depends on $@. | json-schema-validator.js:25:34:25:47 | req.query.data | a user-provided value | | marsdb-flow-to.js:14:17:14:21 | query | marsdb-flow-to.js:11:17:11:24 | req.body | marsdb-flow-to.js:14:17:14:21 | query | This query depends on $@. | marsdb-flow-to.js:11:17:11:24 | req.body | a user-provided value | | marsdb.js:16:12:16:16 | query | marsdb.js:13:17:13:24 | req.body | marsdb.js:16:12:16:16 | query | This query depends on $@. | marsdb.js:13:17:13:24 | req.body | a user-provided value | | minimongo.js:18:12:18:16 | query | minimongo.js:15:17:15:24 | req.body | minimongo.js:18:12:18:16 | query | This query depends on $@. | minimongo.js:15:17:15:24 | req.body | a user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-089/untyped/json-schema-validator.js b/javascript/ql/test/query-tests/Security/CWE-089/untyped/json-schema-validator.js new file mode 100644 index 00000000000..93f09a51adb --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-089/untyped/json-schema-validator.js @@ -0,0 +1,37 @@ +import Ajv from 'ajv'; +import express from 'express'; +import { MongoClient } from 'mongodb'; + +const app = express(); + +const schema = { + type: 'object', + properties: { + date: { type: 'string' }, + title: { type: 'string' }, + }, +}; +const ajv = new Ajv(); +const checkSchema = ajv.compile(schema); + +function validate(x) { + return x != null; +} + +app.post('/documents/find', (req, res) => { + MongoClient.connect('mongodb://localhost:27017/test', (err, db) => { + let doc = db.collection('doc'); + + const query = JSON.parse(req.query.data); + if (checkSchema(query)) { + doc.find(query); // OK + } + if (ajv.validate(schema, query)) { + doc.find(query); // OK + } + if (validate(query)) { + doc.find(query); // NOT OK - validate() doesn't sanitize + } + doc.find(query); // NOT OK + }); +}); diff --git a/javascript/ql/test/query-tests/Security/CWE-400/DeepObjectResourceExhaustion/DeepObjectResourceExhaustion.expected b/javascript/ql/test/query-tests/Security/CWE-400/DeepObjectResourceExhaustion/DeepObjectResourceExhaustion.expected new file mode 100644 index 00000000000..c93bc1c7111 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-400/DeepObjectResourceExhaustion/DeepObjectResourceExhaustion.expected @@ -0,0 +1,8 @@ +nodes +| tst.js:9:29:9:36 | req.body | +| tst.js:9:29:9:36 | req.body | +| tst.js:9:29:9:36 | req.body | +edges +| tst.js:9:29:9:36 | req.body | tst.js:9:29:9:36 | req.body | +#select +| tst.js:9:29:9:36 | req.body | tst.js:9:29:9:36 | req.body | tst.js:9:29:9:36 | req.body | Denial of service caused by processing user input from $@ with $@. | tst.js:9:29:9:36 | req.body | here | tst.js:4:21:4:35 | allErrors: true | allErrors: true | diff --git a/javascript/ql/test/query-tests/Security/CWE-400/DeepObjectResourceExhaustion/DeepObjectResourceExhaustion.qlref b/javascript/ql/test/query-tests/Security/CWE-400/DeepObjectResourceExhaustion/DeepObjectResourceExhaustion.qlref new file mode 100644 index 00000000000..659d91ba4b8 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-400/DeepObjectResourceExhaustion/DeepObjectResourceExhaustion.qlref @@ -0,0 +1 @@ +Security/CWE-400/DeepObjectResourceExhaustion.ql \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Security/CWE-400/DeepObjectResourceExhaustion/tst.js b/javascript/ql/test/query-tests/Security/CWE-400/DeepObjectResourceExhaustion/tst.js new file mode 100644 index 00000000000..9ecdad2dbbc --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-400/DeepObjectResourceExhaustion/tst.js @@ -0,0 +1,12 @@ +import express from 'express'; +import Ajv from 'ajv'; + +let ajv = new Ajv({ allErrors: true }); +ajv.addSchema(require('./input-schema'), 'input'); + +var app = express(); +app.get('/user/:id', function(req, res) { + if (!ajv.validate('input', req.body)) { // NOT OK + return; + } +}); diff --git a/javascript/ql/test/query-tests/Security/CWE-400/RemotePropertyInjection.expected b/javascript/ql/test/query-tests/Security/CWE-400/RemovePropertyInjection/RemotePropertyInjection.expected similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-400/RemotePropertyInjection.expected rename to javascript/ql/test/query-tests/Security/CWE-400/RemovePropertyInjection/RemotePropertyInjection.expected diff --git a/javascript/ql/test/query-tests/Security/CWE-400/RemotePropertyInjection.qlref b/javascript/ql/test/query-tests/Security/CWE-400/RemovePropertyInjection/RemotePropertyInjection.qlref similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-400/RemotePropertyInjection.qlref rename to javascript/ql/test/query-tests/Security/CWE-400/RemovePropertyInjection/RemotePropertyInjection.qlref diff --git a/javascript/ql/test/query-tests/Security/CWE-400/tst.js b/javascript/ql/test/query-tests/Security/CWE-400/RemovePropertyInjection/tst.js similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-400/tst.js rename to javascript/ql/test/query-tests/Security/CWE-400/RemovePropertyInjection/tst.js diff --git a/javascript/ql/test/query-tests/Security/CWE-400/tstNonExpr.js b/javascript/ql/test/query-tests/Security/CWE-400/RemovePropertyInjection/tstNonExpr.js similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-400/tstNonExpr.js rename to javascript/ql/test/query-tests/Security/CWE-400/RemovePropertyInjection/tstNonExpr.js diff --git a/javascript/upgrades/930898a4fe07cb48de46800904922ca118b31e50/old.dbscheme b/javascript/upgrades/930898a4fe07cb48de46800904922ca118b31e50/old.dbscheme new file mode 100644 index 00000000000..930898a4fe0 --- /dev/null +++ b/javascript/upgrades/930898a4fe07cb48de46800904922ca118b31e50/old.dbscheme @@ -0,0 +1,1206 @@ +/*** Standard fragments ***/ + +/** Files and folders **/ + +@location = @location_default; + +locations_default(unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref + ); + +@sourceline = @locatable; + +numlines(int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref + ); + + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files(unique int id: @file, + varchar(900) name: string ref, + varchar(900) simple: string ref, + varchar(900) ext: string ref, + int fromSource: int ref); + +folders(unique int id: @folder, + varchar(900) name: string ref, + varchar(900) simple: string ref); + + +@container = @folder | @file ; + + +containerparent(int parent: @container ref, + unique int child: @container ref); + +/** Duplicate code **/ + +duplicateCode( + unique int id : @duplication, + varchar(900) relativePath : string ref, + int equivClass : int ref); + +similarCode( + unique int id : @similarity, + varchar(900) relativePath : string ref, + int equivClass : int ref); + +@duplication_or_similarity = @duplication | @similarity; + +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref); + +/** External data **/ + +externalData( + int id : @externalDataElement, + varchar(900) path : string ref, + int column: int ref, + varchar(900) value : string ref +); + +snapshotDate(unique date snapshotDate : date ref); + +sourceLocationPrefix(varchar(900) prefix : string ref); + +/** Version control data **/ + +svnentries( + int id : @svnentry, + varchar(500) revision : string ref, + varchar(500) author : string ref, + date revisionDate : date ref, + int changeSize : int ref +); + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + varchar(500) action : string ref +); + +svnentrymsg( + int id : @svnentry ref, + varchar(500) message : string ref +); + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +); + + +/*** JavaScript-specific part ***/ + +filetype( + int file: @file ref, + string filetype: string ref +) + +// top-level code fragments +toplevels (unique int id: @toplevel, + int kind: int ref); + +is_externs (int toplevel: @toplevel ref); + +case @toplevel.kind of + 0 = @script +| 1 = @inline_script +| 2 = @event_handler +| 3 = @javascript_url +| 4 = @angular_template_toplevel; + +is_module (int tl: @toplevel ref); +is_nodejs (int tl: @toplevel ref); +is_es2015_module (int tl: @toplevel ref); +is_closure_module (int tl: @toplevel ref); + +@xml_node_with_code = @xmlelement | @xmlattribute; +toplevel_parent_xml_node( + unique int toplevel: @toplevel ref, + int xmlnode: @xml_node_with_code ref); + +xml_element_parent_expression( + unique int xmlnode: @xmlelement ref, + int expression: @expr ref, + int index: int ref); + +// statements +#keyset[parent, idx] +stmts (unique int id: @stmt, + int kind: int ref, + int parent: @stmt_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +stmt_containers (unique int stmt: @stmt ref, + int container: @stmt_container ref); + +jump_targets (unique int jump: @stmt ref, + int target: @stmt ref); + +@stmt_parent = @stmt | @toplevel | @function_expr | @arrow_function_expr; +@stmt_container = @toplevel | @function | @namespace_declaration | @external_module_declaration | @global_augmentation_declaration; + +case @stmt.kind of + 0 = @empty_stmt +| 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @labeled_stmt +| 5 = @break_stmt +| 6 = @continue_stmt +| 7 = @with_stmt +| 8 = @switch_stmt +| 9 = @return_stmt +| 10 = @throw_stmt +| 11 = @try_stmt +| 12 = @while_stmt +| 13 = @do_while_stmt +| 14 = @for_stmt +| 15 = @for_in_stmt +| 16 = @debugger_stmt +| 17 = @function_decl_stmt +| 18 = @var_decl_stmt +| 19 = @case +| 20 = @catch_clause +| 21 = @for_of_stmt +| 22 = @const_decl_stmt +| 23 = @let_stmt +| 24 = @legacy_let_stmt +| 25 = @for_each_stmt +| 26 = @class_decl_stmt +| 27 = @import_declaration +| 28 = @export_all_declaration +| 29 = @export_default_declaration +| 30 = @export_named_declaration +| 31 = @namespace_declaration +| 32 = @import_equals_declaration +| 33 = @export_assign_declaration +| 34 = @interface_declaration +| 35 = @type_alias_declaration +| 36 = @enum_declaration +| 37 = @external_module_declaration +| 38 = @export_as_namespace_declaration +| 39 = @global_augmentation_declaration +; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @let_stmt | @legacy_let_stmt; + +@export_declaration = @export_all_declaration | @export_default_declaration | @export_named_declaration; + +@namespace_definition = @namespace_declaration | @enum_declaration; +@type_definition = @class_definition | @interface_declaration | @enum_declaration | @type_alias_declaration | @enum_member; + +is_instantiated(unique int decl: @namespace_declaration ref); + +@declarable_node = @decl_stmt | @namespace_declaration | @class_decl_stmt | @function_decl_stmt | @enum_declaration | @external_module_declaration | @global_augmentation_declaration | @field; +has_declare_keyword(unique int stmt: @declarable_node ref); + +is_for_await_of(unique int forof: @for_of_stmt ref); + +// expressions +#keyset[parent, idx] +exprs (unique int id: @expr, + int kind: int ref, + int parent: @expr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +literals (varchar(900) value: string ref, + varchar(900) raw: string ref, + unique int expr: @expr_or_type ref); + +enclosing_stmt (unique int expr: @expr_or_type ref, + int stmt: @stmt ref); + +expr_containers (unique int expr: @expr_or_type ref, + int container: @stmt_container ref); + +array_size (unique int ae: @arraylike ref, + int sz: int ref); + +is_delegating (int yield: @yield_expr ref); + +@expr_or_stmt = @expr | @stmt; +@expr_or_type = @expr | @typeexpr; +@expr_parent = @expr_or_stmt | @property | @function_typeexpr; +@arraylike = @array_expr | @array_pattern; +@type_annotation = @typeexpr | @jsdoc_type_expr; +@node_in_stmt_container = @cfg_node | @type_annotation | @toplevel; + +case @expr.kind of + 0 = @label +| 1 = @null_literal +| 2 = @boolean_literal +| 3 = @number_literal +| 4 = @string_literal +| 5 = @regexp_literal +| 6 = @this_expr +| 7 = @array_expr +| 8 = @obj_expr +| 9 = @function_expr +| 10 = @seq_expr +| 11 = @conditional_expr +| 12 = @new_expr +| 13 = @call_expr +| 14 = @dot_expr +| 15 = @index_expr +| 16 = @neg_expr +| 17 = @plus_expr +| 18 = @log_not_expr +| 19 = @bit_not_expr +| 20 = @typeof_expr +| 21 = @void_expr +| 22 = @delete_expr +| 23 = @eq_expr +| 24 = @neq_expr +| 25 = @eqq_expr +| 26 = @neqq_expr +| 27 = @lt_expr +| 28 = @le_expr +| 29 = @gt_expr +| 30 = @ge_expr +| 31 = @lshift_expr +| 32 = @rshift_expr +| 33 = @urshift_expr +| 34 = @add_expr +| 35 = @sub_expr +| 36 = @mul_expr +| 37 = @div_expr +| 38 = @mod_expr +| 39 = @bitor_expr +| 40 = @xor_expr +| 41 = @bitand_expr +| 42 = @in_expr +| 43 = @instanceof_expr +| 44 = @logand_expr +| 45 = @logor_expr +| 47 = @assign_expr +| 48 = @assign_add_expr +| 49 = @assign_sub_expr +| 50 = @assign_mul_expr +| 51 = @assign_div_expr +| 52 = @assign_mod_expr +| 53 = @assign_lshift_expr +| 54 = @assign_rshift_expr +| 55 = @assign_urshift_expr +| 56 = @assign_or_expr +| 57 = @assign_xor_expr +| 58 = @assign_and_expr +| 59 = @preinc_expr +| 60 = @postinc_expr +| 61 = @predec_expr +| 62 = @postdec_expr +| 63 = @par_expr +| 64 = @var_declarator +| 65 = @arrow_function_expr +| 66 = @spread_element +| 67 = @array_pattern +| 68 = @object_pattern +| 69 = @yield_expr +| 70 = @tagged_template_expr +| 71 = @template_literal +| 72 = @template_element +| 73 = @array_comprehension_expr +| 74 = @generator_expr +| 75 = @for_in_comprehension_block +| 76 = @for_of_comprehension_block +| 77 = @legacy_letexpr +| 78 = @var_decl +| 79 = @proper_varaccess +| 80 = @class_expr +| 81 = @super_expr +| 82 = @newtarget_expr +| 83 = @named_import_specifier +| 84 = @import_default_specifier +| 85 = @import_namespace_specifier +| 86 = @named_export_specifier +| 87 = @exp_expr +| 88 = @assign_exp_expr +| 89 = @jsx_element +| 90 = @jsx_qualified_name +| 91 = @jsx_empty_expr +| 92 = @await_expr +| 93 = @function_sent_expr +| 94 = @decorator +| 95 = @export_default_specifier +| 96 = @export_namespace_specifier +| 97 = @bind_expr +| 98 = @external_module_reference +| 99 = @dynamic_import +| 100 = @expression_with_type_arguments +| 101 = @prefix_type_assertion +| 102 = @as_type_assertion +| 103 = @export_varaccess +| 104 = @decorator_list +| 105 = @non_null_assertion +| 106 = @bigint_literal +| 107 = @nullishcoalescing_expr +| 108 = @e4x_xml_anyname +| 109 = @e4x_xml_static_attribute_selector +| 110 = @e4x_xml_dynamic_attribute_selector +| 111 = @e4x_xml_filter_expression +| 112 = @e4x_xml_static_qualident +| 113 = @e4x_xml_dynamic_qualident +| 114 = @e4x_xml_dotdotexpr +| 115 = @import_meta_expr +| 116 = @assignlogandexpr +| 117 = @assignlogorexpr +| 118 = @assignnullishcoalescingexpr +| 119 = @angular_pipe_ref +; + +@varaccess = @proper_varaccess | @export_varaccess; +@varref = @var_decl | @varaccess; + +@identifier = @label | @varref | @type_identifier; + +@literal = @null_literal | @boolean_literal | @number_literal | @string_literal | @regexp_literal | @bigint_literal; + +@propaccess = @dot_expr | @index_expr; + +@invokeexpr = @new_expr | @call_expr; + +@unaryexpr = @neg_expr | @plus_expr | @log_not_expr | @bit_not_expr | @typeof_expr | @void_expr | @delete_expr | @spread_element; + +@equality_test = @eq_expr | @neq_expr | @eqq_expr | @neqq_expr; + +@comparison = @equality_test | @lt_expr | @le_expr | @gt_expr | @ge_expr; + +@binaryexpr = @comparison | @lshift_expr | @rshift_expr | @urshift_expr | @add_expr | @sub_expr | @mul_expr | @div_expr | @mod_expr | @exp_expr | @bitor_expr | @xor_expr | @bitand_expr | @in_expr | @instanceof_expr | @logand_expr | @logor_expr | @nullishcoalescing_expr; + +@assignment = @assign_expr | @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr | @assign_mod_expr | @assign_exp_expr | @assign_lshift_expr | @assign_rshift_expr | @assign_urshift_expr | @assign_or_expr | @assign_xor_expr | @assign_and_expr | @assignlogandexpr | @assignlogorexpr | @assignnullishcoalescingexpr; + +@updateexpr = @preinc_expr | @postinc_expr | @predec_expr | @postdec_expr; + +@pattern = @varref | @array_pattern | @object_pattern; + +@comprehension_expr = @array_comprehension_expr | @generator_expr; + +@comprehension_block = @for_in_comprehension_block | @for_of_comprehension_block; + +@import_specifier = @named_import_specifier | @import_default_specifier | @import_namespace_specifier; + +@exportspecifier = @named_export_specifier | @export_default_specifier | @export_namespace_specifier; + +@import_or_export_declaration = @import_declaration | @export_declaration; + +@type_assertion = @as_type_assertion | @prefix_type_assertion; + +@class_definition = @class_decl_stmt | @class_expr; +@interface_definition = @interface_declaration | @interface_typeexpr; +@class_or_interface = @class_definition | @interface_definition; + +@lexical_decl = @var_decl | @type_decl; +@lexical_access = @varaccess | @local_type_access | @local_var_type_access | @local_namespace_access; +@lexical_ref = @lexical_decl | @lexical_access; + +@e4x_xml_attribute_selector = @e4x_xml_static_attribute_selector | @e4x_xml_dynamic_attribute_selector; +@e4x_xml_qualident = @e4x_xml_static_qualident | @e4x_xml_dynamic_qualident; + +// scopes +scopes (unique int id: @scope, + int kind: int ref); + +case @scope.kind of + 0 = @global_scope +| 1 = @function_scope +| 2 = @catch_scope +| 3 = @module_scope +| 4 = @block_scope +| 5 = @for_scope +| 6 = @for_in_scope // for-of scopes work the same as for-in scopes +| 7 = @comprehension_block_scope +| 8 = @class_expr_scope +| 9 = @namespace_scope +| 10 = @class_decl_scope +| 11 = @interface_scope +| 12 = @type_alias_scope +| 13 = @mapped_type_scope +| 14 = @enum_scope +| 15 = @external_module_scope +| 16 = @conditional_type_scope; + +scopenodes (unique int node: @ast_node ref, + int scope: @scope ref); + +scopenesting (unique int inner: @scope ref, + int outer: @scope ref); + +// functions +@function = @function_decl_stmt | @function_expr | @arrow_function_expr; + +@parameterized = @function | @catch_clause; +@type_parameterized = @function | @class_or_interface | @type_alias_declaration | @mapped_typeexpr | @infer_typeexpr; + +is_generator (int fun: @function ref); +has_rest_parameter (int fun: @function ref); +is_async (int fun: @function ref); + +// variables and lexically scoped type names +#keyset[scope, name] +variables (unique int id: @variable, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_type_names (unique int id: @local_type_name, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_namespace_names (unique int id: @local_namespace_name, + varchar(900) name: string ref, + int scope: @scope ref); + +is_arguments_object (int id: @variable ref); + +@lexical_name = @variable | @local_type_name | @local_namespace_name; + +@bind_id = @varaccess | @local_var_type_access; +bind (unique int id: @bind_id ref, + int decl: @variable ref); + +decl (unique int id: @var_decl ref, + int decl: @variable ref); + +@typebind_id = @local_type_access | @export_varaccess; +typebind (unique int id: @typebind_id ref, + int decl: @local_type_name ref); + +@typedecl_id = @type_decl | @var_decl; +typedecl (unique int id: @typedecl_id ref, + int decl: @local_type_name ref); + +namespacedecl (unique int id: @var_decl ref, + int decl: @local_namespace_name ref); + +@namespacebind_id = @local_namespace_access | @export_varaccess; +namespacebind (unique int id: @namespacebind_id ref, + int decl: @local_namespace_name ref); + + +// properties in object literals, property patterns in object patterns, and method declarations in classes +#keyset[parent, index] +properties (unique int id: @property, + int parent: @property_parent ref, + int index: int ref, + int kind: int ref, + varchar(900) tostring: string ref); + +case @property.kind of + 0 = @value_property +| 1 = @property_getter +| 2 = @property_setter +| 3 = @jsx_attribute +| 4 = @function_call_signature +| 5 = @constructor_call_signature +| 6 = @index_signature +| 7 = @enum_member +| 8 = @proper_field +| 9 = @parameter_field +; + +@property_parent = @obj_expr | @object_pattern | @class_definition | @jsx_element | @interface_definition | @enum_declaration; +@property_accessor = @property_getter | @property_setter; +@call_signature = @function_call_signature | @constructor_call_signature; +@field = @proper_field | @parameter_field; +@field_or_vardeclarator = @field | @var_declarator; + +is_computed (int id: @property ref); +is_method (int id: @property ref); +is_static (int id: @property ref); +is_abstract_member (int id: @property ref); +is_const_enum (int id: @enum_declaration ref); +is_abstract_class (int id: @class_decl_stmt ref); + +has_public_keyword (int id: @property ref); +has_private_keyword (int id: @property ref); +has_protected_keyword (int id: @property ref); +has_readonly_keyword (int id: @property ref); +has_type_keyword (int id: @import_or_export_declaration ref); +is_optional_member (int id: @property ref); +has_definite_assignment_assertion (int id: @field_or_vardeclarator ref); +is_optional_parameter_declaration (unique int parameter: @pattern ref); + +#keyset[constructor, param_index] +parameter_fields( + unique int field: @parameter_field ref, + int constructor: @function_expr ref, + int param_index: int ref +); + +// types +#keyset[parent, idx] +typeexprs ( + unique int id: @typeexpr, + int kind: int ref, + int parent: @typeexpr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref +); + +case @typeexpr.kind of + 0 = @local_type_access +| 1 = @type_decl +| 2 = @keyword_typeexpr +| 3 = @string_literal_typeexpr +| 4 = @number_literal_typeexpr +| 5 = @boolean_literal_typeexpr +| 6 = @array_typeexpr +| 7 = @union_typeexpr +| 8 = @indexed_access_typeexpr +| 9 = @intersection_typeexpr +| 10 = @parenthesized_typeexpr +| 11 = @tuple_typeexpr +| 12 = @keyof_typeexpr +| 13 = @qualified_type_access +| 14 = @generic_typeexpr +| 15 = @type_label +| 16 = @typeof_typeexpr +| 17 = @local_var_type_access +| 18 = @qualified_var_type_access +| 19 = @this_var_type_access +| 20 = @predicate_typeexpr +| 21 = @interface_typeexpr +| 22 = @type_parameter +| 23 = @plain_function_typeexpr +| 24 = @constructor_typeexpr +| 25 = @local_namespace_access +| 26 = @qualified_namespace_access +| 27 = @mapped_typeexpr +| 28 = @conditional_typeexpr +| 29 = @infer_typeexpr +| 30 = @import_type_access +| 31 = @import_namespace_access +| 32 = @import_var_type_access +| 33 = @optional_typeexpr +| 34 = @rest_typeexpr +| 35 = @bigint_literal_typeexpr +| 36 = @readonly_typeexpr +| 37 = @template_literal_typeexpr +; + +@typeref = @typeaccess | @type_decl; +@type_identifier = @type_decl | @local_type_access | @type_label | @local_var_type_access | @local_namespace_access; +@typeexpr_parent = @expr | @stmt | @property | @typeexpr; +@literal_typeexpr = @string_literal_typeexpr | @number_literal_typeexpr | @boolean_literal_typeexpr | @bigint_literal_typeexpr; +@typeaccess = @local_type_access | @qualified_type_access | @import_type_access; +@vartypeaccess = @local_var_type_access | @qualified_var_type_access | @this_var_type_access | @import_var_type_access; +@namespace_access = @local_namespace_access | @qualified_namespace_access | @import_namespace_access; +@import_typeexpr = @import_type_access | @import_namespace_access | @import_var_type_access; + +@function_typeexpr = @plain_function_typeexpr | @constructor_typeexpr; + +// types +types ( + unique int id: @type, + int kind: int ref, + varchar(900) tostring: string ref +); + +#keyset[parent, idx] +type_child ( + int child: @type ref, + int parent: @type ref, + int idx: int ref +); + +case @type.kind of + 0 = @any_type +| 1 = @string_type +| 2 = @number_type +| 3 = @union_type +| 4 = @true_type +| 5 = @false_type +| 6 = @type_reference +| 7 = @object_type +| 8 = @canonical_type_variable_type +| 9 = @typeof_type +| 10 = @void_type +| 11 = @undefined_type +| 12 = @null_type +| 13 = @never_type +| 14 = @plain_symbol_type +| 15 = @unique_symbol_type +| 16 = @objectkeyword_type +| 17 = @intersection_type +| 18 = @tuple_type +| 19 = @lexical_type_variable_type +| 20 = @this_type +| 21 = @number_literal_type +| 22 = @string_literal_type +| 23 = @unknown_type +| 24 = @bigint_type +| 25 = @bigint_literal_type +; + +@boolean_literal_type = @true_type | @false_type; +@symbol_type = @plain_symbol_type | @unique_symbol_type; +@union_or_intersection_type = @union_type | @intersection_type; +@typevariable_type = @canonical_type_variable_type | @lexical_type_variable_type; + +has_asserts_keyword(int node: @predicate_typeexpr ref); + +@typed_ast_node = @expr | @typeexpr | @function; +ast_node_type( + unique int node: @typed_ast_node ref, + int typ: @type ref); + +declared_function_signature( + unique int node: @function ref, + int sig: @signature_type ref +); + +invoke_expr_signature( + unique int node: @invokeexpr ref, + int sig: @signature_type ref +); + +invoke_expr_overload_index( + unique int node: @invokeexpr ref, + int index: int ref +); + +symbols ( + unique int id: @symbol, + int kind: int ref, + varchar(900) name: string ref +); + +symbol_parent ( + unique int symbol: @symbol ref, + int parent: @symbol ref +); + +symbol_module ( + int symbol: @symbol ref, + varchar(900) moduleName: string ref +); + +symbol_global ( + int symbol: @symbol ref, + varchar(900) globalName: string ref +); + +case @symbol.kind of + 0 = @root_symbol +| 1 = @member_symbol +| 2 = @other_symbol +; + +@type_with_symbol = @type_reference | @typevariable_type | @typeof_type | @unique_symbol_type; +@ast_node_with_symbol = @type_definition | @namespace_definition | @toplevel | @typeaccess | @namespace_access | @var_decl | @function | @invokeexpr | @import_declaration | @external_module_reference; + +ast_node_symbol( + unique int node: @ast_node_with_symbol ref, + int symbol: @symbol ref); + +type_symbol( + unique int typ: @type_with_symbol ref, + int symbol: @symbol ref); + +#keyset[typ, name] +type_property( + int typ: @type ref, + varchar(900) name: string ref, + int propertyType: @type ref); + +type_alias( + unique int aliasType: @type ref, + int underlyingType: @type ref); + +@literal_type = @string_literal_type | @number_literal_type | @boolean_literal_type | @bigint_literal_type; +@type_with_literal_value = @string_literal_type | @number_literal_type | @bigint_literal_type; +type_literal_value( + unique int typ: @type_with_literal_value ref, + varchar(900) value: string ref); + +signature_types ( + unique int id: @signature_type, + int kind: int ref, + varchar(900) tostring: string ref, + int type_parameters: int ref, + int required_params: int ref +); + +signature_rest_parameter( + unique int sig: @signature_type ref, + int rest_param_arra_type: @type ref +); + +case @signature_type.kind of + 0 = @function_signature_type +| 1 = @constructor_signature_type +; + +#keyset[typ, kind, index] +type_contains_signature ( + int typ: @type ref, + int kind: int ref, // constructor/call/index + int index: int ref, // ordering of overloaded signatures + int sig: @signature_type ref +); + +#keyset[parent, index] +signature_contains_type ( + int child: @type ref, + int parent: @signature_type ref, + int index: int ref +); + +#keyset[sig, index] +signature_parameter_name ( + int sig: @signature_type ref, + int index: int ref, + varchar(900) name: string ref +); + +number_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +string_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +base_type_names( + int typeName: @symbol ref, + int baseTypeName: @symbol ref +); + +self_types( + int typeName: @symbol ref, + int selfType: @type_reference ref +); + +tuple_type_min_length( + unique int typ: @type ref, + int minLength: int ref +); + +tuple_type_rest( + unique int typ: @type ref +); + +// comments +comments (unique int id: @comment, + int kind: int ref, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(900) tostring: string ref); + +case @comment.kind of + 0 = @slashslash_comment +| 1 = @slashstar_comment +| 2 = @doc_comment +| 3 = @html_comment_start +| 4 = @htmlcommentend; + +@html_comment = @html_comment_start | @htmlcommentend; +@line_comment = @slashslash_comment | @html_comment; +@block_comment = @slashstar_comment | @doc_comment; + +// source lines +lines (unique int id: @line, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(2) terminator: string ref); +indentation (int file: @file ref, + int lineno: int ref, + varchar(1) indentChar: string ref, + int indentDepth: int ref); + +// JavaScript parse errors +js_parse_errors (unique int id: @js_parse_error, + int toplevel: @toplevel ref, + varchar(900) message: string ref, + varchar(900) line: string ref); + +// regular expressions +#keyset[parent, idx] +regexpterm (unique int id: @regexpterm, + int kind: int ref, + int parent: @regexpparent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +@regexpparent = @regexpterm | @regexp_literal | @string_literal; + +case @regexpterm.kind of + 0 = @regexp_alt +| 1 = @regexp_seq +| 2 = @regexp_caret +| 3 = @regexp_dollar +| 4 = @regexp_wordboundary +| 5 = @regexp_nonwordboundary +| 6 = @regexp_positive_lookahead +| 7 = @regexp_negative_lookahead +| 8 = @regexp_star +| 9 = @regexp_plus +| 10 = @regexp_opt +| 11 = @regexp_range +| 12 = @regexp_dot +| 13 = @regexp_group +| 14 = @regexp_normal_constant +| 15 = @regexp_hex_escape +| 16 = @regexp_unicode_escape +| 17 = @regexp_dec_escape +| 18 = @regexp_oct_escape +| 19 = @regexp_ctrl_escape +| 20 = @regexp_char_class_escape +| 21 = @regexp_id_escape +| 22 = @regexp_backref +| 23 = @regexp_char_class +| 24 = @regexp_char_range +| 25 = @regexp_positive_lookbehind +| 26 = @regexp_negative_lookbehind +| 27 = @regexp_unicode_property_escape; + +regexp_parse_errors (unique int id: @regexp_parse_error, + int regexp: @regexpterm ref, + varchar(900) message: string ref); + +@regexp_quantifier = @regexp_star | @regexp_plus | @regexp_opt | @regexp_range; +@regexp_escape = @regexp_char_escape | @regexp_char_class_escape | @regexp_unicode_property_escape; +@regexp_char_escape = @regexp_hex_escape | @regexp_unicode_escape | @regexp_dec_escape | @regexp_oct_escape | @regexp_ctrl_escape | @regexp_id_escape; +@regexp_constant = @regexp_normal_constant | @regexp_char_escape; +@regexp_lookahead = @regexp_positive_lookahead | @regexp_negative_lookahead; +@regexp_lookbehind = @regexp_positive_lookbehind | @regexp_negative_lookbehind; +@regexp_subpattern = @regexp_lookahead | @regexp_lookbehind; +@regexp_anchor = @regexp_dollar | @regexp_caret; + +is_greedy (int id: @regexp_quantifier ref); +range_quantifier_lower_bound (unique int id: @regexp_range ref, int lo: int ref); +range_quantifier_upper_bound (unique int id: @regexp_range ref, int hi: int ref); +is_capture (unique int id: @regexp_group ref, int number: int ref); +is_named_capture (unique int id: @regexp_group ref, string name: string ref); +is_inverted (int id: @regexp_char_class ref); +regexp_const_value (unique int id: @regexp_constant ref, varchar(1) value: string ref); +char_class_escape (unique int id: @regexp_char_class_escape ref, varchar(1) value: string ref); +backref (unique int id: @regexp_backref ref, int value: int ref); +named_backref (unique int id: @regexp_backref ref, string name: string ref); +unicode_property_escapename (unique int id: @regexp_unicode_property_escape ref, string name: string ref); +unicode_property_escapevalue (unique int id: @regexp_unicode_property_escape ref, string value: string ref); + +// tokens +#keyset[toplevel, idx] +tokeninfo (unique int id: @token, + int kind: int ref, + int toplevel: @toplevel ref, + int idx: int ref, + varchar(900) value: string ref); + +case @token.kind of + 0 = @token_eof +| 1 = @token_null_literal +| 2 = @token_boolean_literal +| 3 = @token_numeric_literal +| 4 = @token_string_literal +| 5 = @token_regular_expression +| 6 = @token_identifier +| 7 = @token_keyword +| 8 = @token_punctuator; + +// associate comments with the token immediately following them (which may be EOF) +next_token (int comment: @comment ref, int token: @token ref); + +// JSON +#keyset[parent, idx] +json (unique int id: @json_value, + int kind: int ref, + int parent: @json_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +json_literals (varchar(900) value: string ref, + varchar(900) raw: string ref, + unique int expr: @json_value ref); + +json_properties (int obj: @json_object ref, + varchar(900) property: string ref, + int value: @json_value ref); + +json_errors (unique int id: @json_parse_error, + varchar(900) message: string ref); + +json_locations(unique int locatable: @json_locatable ref, + int location: @location_default ref); + +case @json_value.kind of + 0 = @json_null +| 1 = @json_boolean +| 2 = @json_number +| 3 = @json_string +| 4 = @json_array +| 5 = @json_object; + +@json_parent = @json_object | @json_array | @file; + +@json_locatable = @json_value | @json_parse_error; + +// locations +@ast_node = @toplevel | @stmt | @expr | @property | @typeexpr; + +@locatable = @file + | @ast_node + | @comment + | @line + | @js_parse_error | @regexp_parse_error + | @regexpterm + | @json_locatable + | @token + | @cfg_node + | @jsdoc | @jsdoc_type_expr | @jsdoc_tag + | @yaml_locatable + | @xmllocatable + | @configLocatable; + +hasLocation (unique int locatable: @locatable ref, + int location: @location ref); + +// CFG +entry_cfg_node (unique int id: @entry_node, int container: @stmt_container ref); +exit_cfg_node (unique int id: @exit_node, int container: @stmt_container ref); +guard_node (unique int id: @guard_node, int kind: int ref, int test: @expr ref); +case @guard_node.kind of + 0 = @falsy_guard +| 1 = @truthy_guard; +@condition_guard = @falsy_guard | @truthy_guard; + +@synthetic_cfg_node = @entry_node | @exit_node | @guard_node; +@cfg_node = @synthetic_cfg_node | @expr_parent; + +successor (int pred: @cfg_node ref, int succ: @cfg_node ref); + +// JSDoc comments +jsdoc (unique int id: @jsdoc, varchar(900) description: string ref, int comment: @comment ref); +#keyset[parent, idx] +jsdoc_tags (unique int id: @jsdoc_tag, varchar(900) title: string ref, + int parent: @jsdoc ref, int idx: int ref, varchar(900) tostring: string ref); +jsdoc_tag_descriptions (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); +jsdoc_tag_names (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); + +#keyset[parent, idx] +jsdoc_type_exprs (unique int id: @jsdoc_type_expr, + int kind: int ref, + int parent: @jsdoc_type_expr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); +case @jsdoc_type_expr.kind of + 0 = @jsdoc_any_type_expr +| 1 = @jsdoc_null_type_expr +| 2 = @jsdoc_undefined_type_expr +| 3 = @jsdoc_unknown_type_expr +| 4 = @jsdoc_void_type_expr +| 5 = @jsdoc_named_type_expr +| 6 = @jsdoc_applied_type_expr +| 7 = @jsdoc_nullable_type_expr +| 8 = @jsdoc_non_nullable_type_expr +| 9 = @jsdoc_record_type_expr +| 10 = @jsdoc_array_type_expr +| 11 = @jsdoc_union_type_expr +| 12 = @jsdoc_function_type_expr +| 13 = @jsdoc_optional_type_expr +| 14 = @jsdoc_rest_type_expr +; + +#keyset[id, idx] +jsdoc_record_field_name (int id: @jsdoc_record_type_expr ref, int idx: int ref, varchar(900) name: string ref); +jsdoc_prefix_qualifier (int id: @jsdoc_type_expr ref); +jsdoc_has_new_parameter (int fn: @jsdoc_function_type_expr ref); + +@jsdoc_type_expr_parent = @jsdoc_type_expr | @jsdoc_tag; + +jsdoc_errors (unique int id: @jsdoc_error, int tag: @jsdoc_tag ref, varchar(900) message: string ref, varchar(900) tostring: string ref); + +// YAML +#keyset[parent, idx] +yaml (unique int id: @yaml_node, + int kind: int ref, + int parent: @yaml_node_parent ref, + int idx: int ref, + varchar(900) tag: string ref, + varchar(900) tostring: string ref); + +case @yaml_node.kind of + 0 = @yaml_scalar_node +| 1 = @yaml_mapping_node +| 2 = @yaml_sequence_node +| 3 = @yaml_alias_node +; + +@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node; + +@yaml_node_parent = @yaml_collection_node | @file; + +yaml_anchors (unique int node: @yaml_node ref, + varchar(900) anchor: string ref); + +yaml_aliases (unique int alias: @yaml_alias_node ref, + varchar(900) target: string ref); + +yaml_scalars (unique int scalar: @yaml_scalar_node ref, + int style: int ref, + varchar(900) value: string ref); + +yaml_errors (unique int id: @yaml_error, + varchar(900) message: string ref); + +yaml_locations(unique int locatable: @yaml_locatable ref, + int location: @location_default ref); + +@yaml_locatable = @yaml_node | @yaml_error; + +/* XML Files */ + +xmlEncoding( + unique int id: @file ref, + varchar(900) encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + varchar(900) root: string ref, + varchar(900) publicId: string ref, + varchar(900) systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + varchar(900) name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + varchar(900) name: string ref, + varchar(3600) value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + varchar(900) prefixName: string ref, + varchar(900) URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + varchar(3600) text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + varchar(3600) text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +@dataflownode = @expr | @function_decl_stmt | @class_decl_stmt | @namespace_declaration | @enum_declaration | @property; + +@optionalchainable = @call_expr | @propaccess; + +isOptionalChaining(int id: @optionalchainable ref); + +/* + * configuration files with key value pairs + */ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; + +/** + * The time taken for the extraction of a file. + * This table contains non-deterministic content. + * + * The sum of the `time` column for each (`file`, `timerKind`) pair + * is the total time taken for extraction of `file`. The `extractionPhase` + * column provides a granular view of the extraction time of the file. + */ +extraction_time( + int file : @file ref, + // see `com.semmle.js.extractor.ExtractionMetrics.ExtractionPhase`. + int extractionPhase: int ref, + // 0 for the elapsed CPU time in nanoseconds, 1 for the elapsed wallclock time in nanoseconds + int timerKind: int ref, + float time: float ref +) + +/** + * Non-timing related data for the extraction of a single file. + * This table contains non-deterministic content. + */ +extraction_data( + int file : @file ref, + // the absolute path to the cache file + varchar(900) cacheFile: string ref, + boolean fromCache: boolean ref, + int length: int ref +) diff --git a/javascript/upgrades/930898a4fe07cb48de46800904922ca118b31e50/semmlecode.javascript.dbscheme b/javascript/upgrades/930898a4fe07cb48de46800904922ca118b31e50/semmlecode.javascript.dbscheme new file mode 100644 index 00000000000..fbd45f6b3c6 --- /dev/null +++ b/javascript/upgrades/930898a4fe07cb48de46800904922ca118b31e50/semmlecode.javascript.dbscheme @@ -0,0 +1,1211 @@ +/*** Standard fragments ***/ + +/** Files and folders **/ + +@location = @location_default; + +locations_default(unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref + ); + +@sourceline = @locatable; + +numlines(int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref + ); + + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files(unique int id: @file, + varchar(900) name: string ref, + varchar(900) simple: string ref, + varchar(900) ext: string ref, + int fromSource: int ref); + +folders(unique int id: @folder, + varchar(900) name: string ref, + varchar(900) simple: string ref); + + +@container = @folder | @file ; + + +containerparent(int parent: @container ref, + unique int child: @container ref); + +/** Duplicate code **/ + +duplicateCode( + unique int id : @duplication, + varchar(900) relativePath : string ref, + int equivClass : int ref); + +similarCode( + unique int id : @similarity, + varchar(900) relativePath : string ref, + int equivClass : int ref); + +@duplication_or_similarity = @duplication | @similarity; + +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref); + +/** External data **/ + +externalData( + int id : @externalDataElement, + varchar(900) path : string ref, + int column: int ref, + varchar(900) value : string ref +); + +snapshotDate(unique date snapshotDate : date ref); + +sourceLocationPrefix(varchar(900) prefix : string ref); + +/** Version control data **/ + +svnentries( + int id : @svnentry, + varchar(500) revision : string ref, + varchar(500) author : string ref, + date revisionDate : date ref, + int changeSize : int ref +); + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + varchar(500) action : string ref +); + +svnentrymsg( + int id : @svnentry ref, + varchar(500) message : string ref +); + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +); + + +/*** JavaScript-specific part ***/ + +filetype( + int file: @file ref, + string filetype: string ref +) + +// top-level code fragments +toplevels (unique int id: @toplevel, + int kind: int ref); + +is_externs (int toplevel: @toplevel ref); + +case @toplevel.kind of + 0 = @script +| 1 = @inline_script +| 2 = @event_handler +| 3 = @javascript_url +| 4 = @angular_template_toplevel; + +is_module (int tl: @toplevel ref); +is_nodejs (int tl: @toplevel ref); +is_es2015_module (int tl: @toplevel ref); +is_closure_module (int tl: @toplevel ref); + +@xml_node_with_code = @xmlelement | @xmlattribute; +toplevel_parent_xml_node( + unique int toplevel: @toplevel ref, + int xmlnode: @xml_node_with_code ref); + +xml_element_parent_expression( + unique int xmlnode: @xmlelement ref, + int expression: @expr ref, + int index: int ref); + +// statements +#keyset[parent, idx] +stmts (unique int id: @stmt, + int kind: int ref, + int parent: @stmt_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +stmt_containers (unique int stmt: @stmt ref, + int container: @stmt_container ref); + +jump_targets (unique int jump: @stmt ref, + int target: @stmt ref); + +@stmt_parent = @stmt | @toplevel | @function_expr | @arrow_function_expr; +@stmt_container = @toplevel | @function | @namespace_declaration | @external_module_declaration | @global_augmentation_declaration; + +case @stmt.kind of + 0 = @empty_stmt +| 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @labeled_stmt +| 5 = @break_stmt +| 6 = @continue_stmt +| 7 = @with_stmt +| 8 = @switch_stmt +| 9 = @return_stmt +| 10 = @throw_stmt +| 11 = @try_stmt +| 12 = @while_stmt +| 13 = @do_while_stmt +| 14 = @for_stmt +| 15 = @for_in_stmt +| 16 = @debugger_stmt +| 17 = @function_decl_stmt +| 18 = @var_decl_stmt +| 19 = @case +| 20 = @catch_clause +| 21 = @for_of_stmt +| 22 = @const_decl_stmt +| 23 = @let_stmt +| 24 = @legacy_let_stmt +| 25 = @for_each_stmt +| 26 = @class_decl_stmt +| 27 = @import_declaration +| 28 = @export_all_declaration +| 29 = @export_default_declaration +| 30 = @export_named_declaration +| 31 = @namespace_declaration +| 32 = @import_equals_declaration +| 33 = @export_assign_declaration +| 34 = @interface_declaration +| 35 = @type_alias_declaration +| 36 = @enum_declaration +| 37 = @external_module_declaration +| 38 = @export_as_namespace_declaration +| 39 = @global_augmentation_declaration +; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @let_stmt | @legacy_let_stmt; + +@export_declaration = @export_all_declaration | @export_default_declaration | @export_named_declaration; + +@namespace_definition = @namespace_declaration | @enum_declaration; +@type_definition = @class_definition | @interface_declaration | @enum_declaration | @type_alias_declaration | @enum_member; + +is_instantiated(unique int decl: @namespace_declaration ref); + +@declarable_node = @decl_stmt | @namespace_declaration | @class_decl_stmt | @function_decl_stmt | @enum_declaration | @external_module_declaration | @global_augmentation_declaration | @field; +has_declare_keyword(unique int stmt: @declarable_node ref); + +is_for_await_of(unique int forof: @for_of_stmt ref); + +// expressions +#keyset[parent, idx] +exprs (unique int id: @expr, + int kind: int ref, + int parent: @expr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +literals (varchar(900) value: string ref, + varchar(900) raw: string ref, + unique int expr: @expr_or_type ref); + +enclosing_stmt (unique int expr: @expr_or_type ref, + int stmt: @stmt ref); + +expr_containers (unique int expr: @expr_or_type ref, + int container: @stmt_container ref); + +array_size (unique int ae: @arraylike ref, + int sz: int ref); + +is_delegating (int yield: @yield_expr ref); + +@expr_or_stmt = @expr | @stmt; +@expr_or_type = @expr | @typeexpr; +@expr_parent = @expr_or_stmt | @property | @function_typeexpr; +@arraylike = @array_expr | @array_pattern; +@type_annotation = @typeexpr | @jsdoc_type_expr; +@node_in_stmt_container = @cfg_node | @type_annotation | @toplevel; + +case @expr.kind of + 0 = @label +| 1 = @null_literal +| 2 = @boolean_literal +| 3 = @number_literal +| 4 = @string_literal +| 5 = @regexp_literal +| 6 = @this_expr +| 7 = @array_expr +| 8 = @obj_expr +| 9 = @function_expr +| 10 = @seq_expr +| 11 = @conditional_expr +| 12 = @new_expr +| 13 = @call_expr +| 14 = @dot_expr +| 15 = @index_expr +| 16 = @neg_expr +| 17 = @plus_expr +| 18 = @log_not_expr +| 19 = @bit_not_expr +| 20 = @typeof_expr +| 21 = @void_expr +| 22 = @delete_expr +| 23 = @eq_expr +| 24 = @neq_expr +| 25 = @eqq_expr +| 26 = @neqq_expr +| 27 = @lt_expr +| 28 = @le_expr +| 29 = @gt_expr +| 30 = @ge_expr +| 31 = @lshift_expr +| 32 = @rshift_expr +| 33 = @urshift_expr +| 34 = @add_expr +| 35 = @sub_expr +| 36 = @mul_expr +| 37 = @div_expr +| 38 = @mod_expr +| 39 = @bitor_expr +| 40 = @xor_expr +| 41 = @bitand_expr +| 42 = @in_expr +| 43 = @instanceof_expr +| 44 = @logand_expr +| 45 = @logor_expr +| 47 = @assign_expr +| 48 = @assign_add_expr +| 49 = @assign_sub_expr +| 50 = @assign_mul_expr +| 51 = @assign_div_expr +| 52 = @assign_mod_expr +| 53 = @assign_lshift_expr +| 54 = @assign_rshift_expr +| 55 = @assign_urshift_expr +| 56 = @assign_or_expr +| 57 = @assign_xor_expr +| 58 = @assign_and_expr +| 59 = @preinc_expr +| 60 = @postinc_expr +| 61 = @predec_expr +| 62 = @postdec_expr +| 63 = @par_expr +| 64 = @var_declarator +| 65 = @arrow_function_expr +| 66 = @spread_element +| 67 = @array_pattern +| 68 = @object_pattern +| 69 = @yield_expr +| 70 = @tagged_template_expr +| 71 = @template_literal +| 72 = @template_element +| 73 = @array_comprehension_expr +| 74 = @generator_expr +| 75 = @for_in_comprehension_block +| 76 = @for_of_comprehension_block +| 77 = @legacy_letexpr +| 78 = @var_decl +| 79 = @proper_varaccess +| 80 = @class_expr +| 81 = @super_expr +| 82 = @newtarget_expr +| 83 = @named_import_specifier +| 84 = @import_default_specifier +| 85 = @import_namespace_specifier +| 86 = @named_export_specifier +| 87 = @exp_expr +| 88 = @assign_exp_expr +| 89 = @jsx_element +| 90 = @jsx_qualified_name +| 91 = @jsx_empty_expr +| 92 = @await_expr +| 93 = @function_sent_expr +| 94 = @decorator +| 95 = @export_default_specifier +| 96 = @export_namespace_specifier +| 97 = @bind_expr +| 98 = @external_module_reference +| 99 = @dynamic_import +| 100 = @expression_with_type_arguments +| 101 = @prefix_type_assertion +| 102 = @as_type_assertion +| 103 = @export_varaccess +| 104 = @decorator_list +| 105 = @non_null_assertion +| 106 = @bigint_literal +| 107 = @nullishcoalescing_expr +| 108 = @e4x_xml_anyname +| 109 = @e4x_xml_static_attribute_selector +| 110 = @e4x_xml_dynamic_attribute_selector +| 111 = @e4x_xml_filter_expression +| 112 = @e4x_xml_static_qualident +| 113 = @e4x_xml_dynamic_qualident +| 114 = @e4x_xml_dotdotexpr +| 115 = @import_meta_expr +| 116 = @assignlogandexpr +| 117 = @assignlogorexpr +| 118 = @assignnullishcoalescingexpr +| 119 = @angular_pipe_ref +; + +@varaccess = @proper_varaccess | @export_varaccess; +@varref = @var_decl | @varaccess; + +@identifier = @label | @varref | @type_identifier; + +@literal = @null_literal | @boolean_literal | @number_literal | @string_literal | @regexp_literal | @bigint_literal; + +@propaccess = @dot_expr | @index_expr; + +@invokeexpr = @new_expr | @call_expr; + +@unaryexpr = @neg_expr | @plus_expr | @log_not_expr | @bit_not_expr | @typeof_expr | @void_expr | @delete_expr | @spread_element; + +@equality_test = @eq_expr | @neq_expr | @eqq_expr | @neqq_expr; + +@comparison = @equality_test | @lt_expr | @le_expr | @gt_expr | @ge_expr; + +@binaryexpr = @comparison | @lshift_expr | @rshift_expr | @urshift_expr | @add_expr | @sub_expr | @mul_expr | @div_expr | @mod_expr | @exp_expr | @bitor_expr | @xor_expr | @bitand_expr | @in_expr | @instanceof_expr | @logand_expr | @logor_expr | @nullishcoalescing_expr; + +@assignment = @assign_expr | @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr | @assign_mod_expr | @assign_exp_expr | @assign_lshift_expr | @assign_rshift_expr | @assign_urshift_expr | @assign_or_expr | @assign_xor_expr | @assign_and_expr | @assignlogandexpr | @assignlogorexpr | @assignnullishcoalescingexpr; + +@updateexpr = @preinc_expr | @postinc_expr | @predec_expr | @postdec_expr; + +@pattern = @varref | @array_pattern | @object_pattern; + +@comprehension_expr = @array_comprehension_expr | @generator_expr; + +@comprehension_block = @for_in_comprehension_block | @for_of_comprehension_block; + +@import_specifier = @named_import_specifier | @import_default_specifier | @import_namespace_specifier; + +@exportspecifier = @named_export_specifier | @export_default_specifier | @export_namespace_specifier; + +@import_or_export_declaration = @import_declaration | @export_declaration; + +@type_assertion = @as_type_assertion | @prefix_type_assertion; + +@class_definition = @class_decl_stmt | @class_expr; +@interface_definition = @interface_declaration | @interface_typeexpr; +@class_or_interface = @class_definition | @interface_definition; + +@lexical_decl = @var_decl | @type_decl; +@lexical_access = @varaccess | @local_type_access | @local_var_type_access | @local_namespace_access; +@lexical_ref = @lexical_decl | @lexical_access; + +@e4x_xml_attribute_selector = @e4x_xml_static_attribute_selector | @e4x_xml_dynamic_attribute_selector; +@e4x_xml_qualident = @e4x_xml_static_qualident | @e4x_xml_dynamic_qualident; + +// scopes +scopes (unique int id: @scope, + int kind: int ref); + +case @scope.kind of + 0 = @global_scope +| 1 = @function_scope +| 2 = @catch_scope +| 3 = @module_scope +| 4 = @block_scope +| 5 = @for_scope +| 6 = @for_in_scope // for-of scopes work the same as for-in scopes +| 7 = @comprehension_block_scope +| 8 = @class_expr_scope +| 9 = @namespace_scope +| 10 = @class_decl_scope +| 11 = @interface_scope +| 12 = @type_alias_scope +| 13 = @mapped_type_scope +| 14 = @enum_scope +| 15 = @external_module_scope +| 16 = @conditional_type_scope; + +scopenodes (unique int node: @ast_node ref, + int scope: @scope ref); + +scopenesting (unique int inner: @scope ref, + int outer: @scope ref); + +// functions +@function = @function_decl_stmt | @function_expr | @arrow_function_expr; + +@parameterized = @function | @catch_clause; +@type_parameterized = @function | @class_or_interface | @type_alias_declaration | @mapped_typeexpr | @infer_typeexpr; + +is_generator (int fun: @function ref); +has_rest_parameter (int fun: @function ref); +is_async (int fun: @function ref); + +// variables and lexically scoped type names +#keyset[scope, name] +variables (unique int id: @variable, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_type_names (unique int id: @local_type_name, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_namespace_names (unique int id: @local_namespace_name, + varchar(900) name: string ref, + int scope: @scope ref); + +is_arguments_object (int id: @variable ref); + +@lexical_name = @variable | @local_type_name | @local_namespace_name; + +@bind_id = @varaccess | @local_var_type_access; +bind (unique int id: @bind_id ref, + int decl: @variable ref); + +decl (unique int id: @var_decl ref, + int decl: @variable ref); + +@typebind_id = @local_type_access | @export_varaccess; +typebind (unique int id: @typebind_id ref, + int decl: @local_type_name ref); + +@typedecl_id = @type_decl | @var_decl; +typedecl (unique int id: @typedecl_id ref, + int decl: @local_type_name ref); + +namespacedecl (unique int id: @var_decl ref, + int decl: @local_namespace_name ref); + +@namespacebind_id = @local_namespace_access | @export_varaccess; +namespacebind (unique int id: @namespacebind_id ref, + int decl: @local_namespace_name ref); + + +// properties in object literals, property patterns in object patterns, and method declarations in classes +#keyset[parent, index] +properties (unique int id: @property, + int parent: @property_parent ref, + int index: int ref, + int kind: int ref, + varchar(900) tostring: string ref); + +case @property.kind of + 0 = @value_property +| 1 = @property_getter +| 2 = @property_setter +| 3 = @jsx_attribute +| 4 = @function_call_signature +| 5 = @constructor_call_signature +| 6 = @index_signature +| 7 = @enum_member +| 8 = @proper_field +| 9 = @parameter_field +; + +@property_parent = @obj_expr | @object_pattern | @class_definition | @jsx_element | @interface_definition | @enum_declaration; +@property_accessor = @property_getter | @property_setter; +@call_signature = @function_call_signature | @constructor_call_signature; +@field = @proper_field | @parameter_field; +@field_or_vardeclarator = @field | @var_declarator; + +is_computed (int id: @property ref); +is_method (int id: @property ref); +is_static (int id: @property ref); +is_abstract_member (int id: @property ref); +is_const_enum (int id: @enum_declaration ref); +is_abstract_class (int id: @class_decl_stmt ref); + +has_public_keyword (int id: @property ref); +has_private_keyword (int id: @property ref); +has_protected_keyword (int id: @property ref); +has_readonly_keyword (int id: @property ref); +has_type_keyword (int id: @import_or_export_declaration ref); +is_optional_member (int id: @property ref); +has_definite_assignment_assertion (int id: @field_or_vardeclarator ref); +is_optional_parameter_declaration (unique int parameter: @pattern ref); + +#keyset[constructor, param_index] +parameter_fields( + unique int field: @parameter_field ref, + int constructor: @function_expr ref, + int param_index: int ref +); + +// types +#keyset[parent, idx] +typeexprs ( + unique int id: @typeexpr, + int kind: int ref, + int parent: @typeexpr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref +); + +case @typeexpr.kind of + 0 = @local_type_access +| 1 = @type_decl +| 2 = @keyword_typeexpr +| 3 = @string_literal_typeexpr +| 4 = @number_literal_typeexpr +| 5 = @boolean_literal_typeexpr +| 6 = @array_typeexpr +| 7 = @union_typeexpr +| 8 = @indexed_access_typeexpr +| 9 = @intersection_typeexpr +| 10 = @parenthesized_typeexpr +| 11 = @tuple_typeexpr +| 12 = @keyof_typeexpr +| 13 = @qualified_type_access +| 14 = @generic_typeexpr +| 15 = @type_label +| 16 = @typeof_typeexpr +| 17 = @local_var_type_access +| 18 = @qualified_var_type_access +| 19 = @this_var_type_access +| 20 = @predicate_typeexpr +| 21 = @interface_typeexpr +| 22 = @type_parameter +| 23 = @plain_function_typeexpr +| 24 = @constructor_typeexpr +| 25 = @local_namespace_access +| 26 = @qualified_namespace_access +| 27 = @mapped_typeexpr +| 28 = @conditional_typeexpr +| 29 = @infer_typeexpr +| 30 = @import_type_access +| 31 = @import_namespace_access +| 32 = @import_var_type_access +| 33 = @optional_typeexpr +| 34 = @rest_typeexpr +| 35 = @bigint_literal_typeexpr +| 36 = @readonly_typeexpr +| 37 = @template_literal_typeexpr +; + +@typeref = @typeaccess | @type_decl; +@type_identifier = @type_decl | @local_type_access | @type_label | @local_var_type_access | @local_namespace_access; +@typeexpr_parent = @expr | @stmt | @property | @typeexpr; +@literal_typeexpr = @string_literal_typeexpr | @number_literal_typeexpr | @boolean_literal_typeexpr | @bigint_literal_typeexpr; +@typeaccess = @local_type_access | @qualified_type_access | @import_type_access; +@vartypeaccess = @local_var_type_access | @qualified_var_type_access | @this_var_type_access | @import_var_type_access; +@namespace_access = @local_namespace_access | @qualified_namespace_access | @import_namespace_access; +@import_typeexpr = @import_type_access | @import_namespace_access | @import_var_type_access; + +@function_typeexpr = @plain_function_typeexpr | @constructor_typeexpr; + +// types +types ( + unique int id: @type, + int kind: int ref, + varchar(900) tostring: string ref +); + +#keyset[parent, idx] +type_child ( + int child: @type ref, + int parent: @type ref, + int idx: int ref +); + +case @type.kind of + 0 = @any_type +| 1 = @string_type +| 2 = @number_type +| 3 = @union_type +| 4 = @true_type +| 5 = @false_type +| 6 = @type_reference +| 7 = @object_type +| 8 = @canonical_type_variable_type +| 9 = @typeof_type +| 10 = @void_type +| 11 = @undefined_type +| 12 = @null_type +| 13 = @never_type +| 14 = @plain_symbol_type +| 15 = @unique_symbol_type +| 16 = @objectkeyword_type +| 17 = @intersection_type +| 18 = @tuple_type +| 19 = @lexical_type_variable_type +| 20 = @this_type +| 21 = @number_literal_type +| 22 = @string_literal_type +| 23 = @unknown_type +| 24 = @bigint_type +| 25 = @bigint_literal_type +; + +@boolean_literal_type = @true_type | @false_type; +@symbol_type = @plain_symbol_type | @unique_symbol_type; +@union_or_intersection_type = @union_type | @intersection_type; +@typevariable_type = @canonical_type_variable_type | @lexical_type_variable_type; + +has_asserts_keyword(int node: @predicate_typeexpr ref); + +@typed_ast_node = @expr | @typeexpr | @function; +ast_node_type( + unique int node: @typed_ast_node ref, + int typ: @type ref); + +declared_function_signature( + unique int node: @function ref, + int sig: @signature_type ref +); + +invoke_expr_signature( + unique int node: @invokeexpr ref, + int sig: @signature_type ref +); + +invoke_expr_overload_index( + unique int node: @invokeexpr ref, + int index: int ref +); + +symbols ( + unique int id: @symbol, + int kind: int ref, + varchar(900) name: string ref +); + +symbol_parent ( + unique int symbol: @symbol ref, + int parent: @symbol ref +); + +symbol_module ( + int symbol: @symbol ref, + varchar(900) moduleName: string ref +); + +symbol_global ( + int symbol: @symbol ref, + varchar(900) globalName: string ref +); + +case @symbol.kind of + 0 = @root_symbol +| 1 = @member_symbol +| 2 = @other_symbol +; + +@type_with_symbol = @type_reference | @typevariable_type | @typeof_type | @unique_symbol_type; +@ast_node_with_symbol = @type_definition | @namespace_definition | @toplevel | @typeaccess | @namespace_access | @var_decl | @function | @invokeexpr | @import_declaration | @external_module_reference; + +ast_node_symbol( + unique int node: @ast_node_with_symbol ref, + int symbol: @symbol ref); + +type_symbol( + unique int typ: @type_with_symbol ref, + int symbol: @symbol ref); + +#keyset[typ, name] +type_property( + int typ: @type ref, + varchar(900) name: string ref, + int propertyType: @type ref); + +type_alias( + unique int aliasType: @type ref, + int underlyingType: @type ref); + +@literal_type = @string_literal_type | @number_literal_type | @boolean_literal_type | @bigint_literal_type; +@type_with_literal_value = @string_literal_type | @number_literal_type | @bigint_literal_type; +type_literal_value( + unique int typ: @type_with_literal_value ref, + varchar(900) value: string ref); + +signature_types ( + unique int id: @signature_type, + int kind: int ref, + varchar(900) tostring: string ref, + int type_parameters: int ref, + int required_params: int ref +); + +is_abstract_signature( + unique int sig: @signature_type ref +); + +signature_rest_parameter( + unique int sig: @signature_type ref, + int rest_param_arra_type: @type ref +); + +case @signature_type.kind of + 0 = @function_signature_type +| 1 = @constructor_signature_type +; + +#keyset[typ, kind, index] +type_contains_signature ( + int typ: @type ref, + int kind: int ref, // constructor/call/index + int index: int ref, // ordering of overloaded signatures + int sig: @signature_type ref +); + +#keyset[parent, index] +signature_contains_type ( + int child: @type ref, + int parent: @signature_type ref, + int index: int ref +); + +#keyset[sig, index] +signature_parameter_name ( + int sig: @signature_type ref, + int index: int ref, + varchar(900) name: string ref +); + +number_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +string_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +base_type_names( + int typeName: @symbol ref, + int baseTypeName: @symbol ref +); + +self_types( + int typeName: @symbol ref, + int selfType: @type_reference ref +); + +tuple_type_min_length( + unique int typ: @type ref, + int minLength: int ref +); + +tuple_type_rest_index( + unique int typ: @type ref, + int index: int ref +); + +// comments +comments (unique int id: @comment, + int kind: int ref, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(900) tostring: string ref); + +case @comment.kind of + 0 = @slashslash_comment +| 1 = @slashstar_comment +| 2 = @doc_comment +| 3 = @html_comment_start +| 4 = @htmlcommentend; + +@html_comment = @html_comment_start | @htmlcommentend; +@line_comment = @slashslash_comment | @html_comment; +@block_comment = @slashstar_comment | @doc_comment; + +// source lines +lines (unique int id: @line, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(2) terminator: string ref); +indentation (int file: @file ref, + int lineno: int ref, + varchar(1) indentChar: string ref, + int indentDepth: int ref); + +// JavaScript parse errors +js_parse_errors (unique int id: @js_parse_error, + int toplevel: @toplevel ref, + varchar(900) message: string ref, + varchar(900) line: string ref); + +// regular expressions +#keyset[parent, idx] +regexpterm (unique int id: @regexpterm, + int kind: int ref, + int parent: @regexpparent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +@regexpparent = @regexpterm | @regexp_literal | @string_literal; + +case @regexpterm.kind of + 0 = @regexp_alt +| 1 = @regexp_seq +| 2 = @regexp_caret +| 3 = @regexp_dollar +| 4 = @regexp_wordboundary +| 5 = @regexp_nonwordboundary +| 6 = @regexp_positive_lookahead +| 7 = @regexp_negative_lookahead +| 8 = @regexp_star +| 9 = @regexp_plus +| 10 = @regexp_opt +| 11 = @regexp_range +| 12 = @regexp_dot +| 13 = @regexp_group +| 14 = @regexp_normal_constant +| 15 = @regexp_hex_escape +| 16 = @regexp_unicode_escape +| 17 = @regexp_dec_escape +| 18 = @regexp_oct_escape +| 19 = @regexp_ctrl_escape +| 20 = @regexp_char_class_escape +| 21 = @regexp_id_escape +| 22 = @regexp_backref +| 23 = @regexp_char_class +| 24 = @regexp_char_range +| 25 = @regexp_positive_lookbehind +| 26 = @regexp_negative_lookbehind +| 27 = @regexp_unicode_property_escape; + +regexp_parse_errors (unique int id: @regexp_parse_error, + int regexp: @regexpterm ref, + varchar(900) message: string ref); + +@regexp_quantifier = @regexp_star | @regexp_plus | @regexp_opt | @regexp_range; +@regexp_escape = @regexp_char_escape | @regexp_char_class_escape | @regexp_unicode_property_escape; +@regexp_char_escape = @regexp_hex_escape | @regexp_unicode_escape | @regexp_dec_escape | @regexp_oct_escape | @regexp_ctrl_escape | @regexp_id_escape; +@regexp_constant = @regexp_normal_constant | @regexp_char_escape; +@regexp_lookahead = @regexp_positive_lookahead | @regexp_negative_lookahead; +@regexp_lookbehind = @regexp_positive_lookbehind | @regexp_negative_lookbehind; +@regexp_subpattern = @regexp_lookahead | @regexp_lookbehind; +@regexp_anchor = @regexp_dollar | @regexp_caret; + +is_greedy (int id: @regexp_quantifier ref); +range_quantifier_lower_bound (unique int id: @regexp_range ref, int lo: int ref); +range_quantifier_upper_bound (unique int id: @regexp_range ref, int hi: int ref); +is_capture (unique int id: @regexp_group ref, int number: int ref); +is_named_capture (unique int id: @regexp_group ref, string name: string ref); +is_inverted (int id: @regexp_char_class ref); +regexp_const_value (unique int id: @regexp_constant ref, varchar(1) value: string ref); +char_class_escape (unique int id: @regexp_char_class_escape ref, varchar(1) value: string ref); +backref (unique int id: @regexp_backref ref, int value: int ref); +named_backref (unique int id: @regexp_backref ref, string name: string ref); +unicode_property_escapename (unique int id: @regexp_unicode_property_escape ref, string name: string ref); +unicode_property_escapevalue (unique int id: @regexp_unicode_property_escape ref, string value: string ref); + +// tokens +#keyset[toplevel, idx] +tokeninfo (unique int id: @token, + int kind: int ref, + int toplevel: @toplevel ref, + int idx: int ref, + varchar(900) value: string ref); + +case @token.kind of + 0 = @token_eof +| 1 = @token_null_literal +| 2 = @token_boolean_literal +| 3 = @token_numeric_literal +| 4 = @token_string_literal +| 5 = @token_regular_expression +| 6 = @token_identifier +| 7 = @token_keyword +| 8 = @token_punctuator; + +// associate comments with the token immediately following them (which may be EOF) +next_token (int comment: @comment ref, int token: @token ref); + +// JSON +#keyset[parent, idx] +json (unique int id: @json_value, + int kind: int ref, + int parent: @json_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +json_literals (varchar(900) value: string ref, + varchar(900) raw: string ref, + unique int expr: @json_value ref); + +json_properties (int obj: @json_object ref, + varchar(900) property: string ref, + int value: @json_value ref); + +json_errors (unique int id: @json_parse_error, + varchar(900) message: string ref); + +json_locations(unique int locatable: @json_locatable ref, + int location: @location_default ref); + +case @json_value.kind of + 0 = @json_null +| 1 = @json_boolean +| 2 = @json_number +| 3 = @json_string +| 4 = @json_array +| 5 = @json_object; + +@json_parent = @json_object | @json_array | @file; + +@json_locatable = @json_value | @json_parse_error; + +// locations +@ast_node = @toplevel | @stmt | @expr | @property | @typeexpr; + +@locatable = @file + | @ast_node + | @comment + | @line + | @js_parse_error | @regexp_parse_error + | @regexpterm + | @json_locatable + | @token + | @cfg_node + | @jsdoc | @jsdoc_type_expr | @jsdoc_tag + | @yaml_locatable + | @xmllocatable + | @configLocatable; + +hasLocation (unique int locatable: @locatable ref, + int location: @location ref); + +// CFG +entry_cfg_node (unique int id: @entry_node, int container: @stmt_container ref); +exit_cfg_node (unique int id: @exit_node, int container: @stmt_container ref); +guard_node (unique int id: @guard_node, int kind: int ref, int test: @expr ref); +case @guard_node.kind of + 0 = @falsy_guard +| 1 = @truthy_guard; +@condition_guard = @falsy_guard | @truthy_guard; + +@synthetic_cfg_node = @entry_node | @exit_node | @guard_node; +@cfg_node = @synthetic_cfg_node | @expr_parent; + +successor (int pred: @cfg_node ref, int succ: @cfg_node ref); + +// JSDoc comments +jsdoc (unique int id: @jsdoc, varchar(900) description: string ref, int comment: @comment ref); +#keyset[parent, idx] +jsdoc_tags (unique int id: @jsdoc_tag, varchar(900) title: string ref, + int parent: @jsdoc ref, int idx: int ref, varchar(900) tostring: string ref); +jsdoc_tag_descriptions (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); +jsdoc_tag_names (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); + +#keyset[parent, idx] +jsdoc_type_exprs (unique int id: @jsdoc_type_expr, + int kind: int ref, + int parent: @jsdoc_type_expr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); +case @jsdoc_type_expr.kind of + 0 = @jsdoc_any_type_expr +| 1 = @jsdoc_null_type_expr +| 2 = @jsdoc_undefined_type_expr +| 3 = @jsdoc_unknown_type_expr +| 4 = @jsdoc_void_type_expr +| 5 = @jsdoc_named_type_expr +| 6 = @jsdoc_applied_type_expr +| 7 = @jsdoc_nullable_type_expr +| 8 = @jsdoc_non_nullable_type_expr +| 9 = @jsdoc_record_type_expr +| 10 = @jsdoc_array_type_expr +| 11 = @jsdoc_union_type_expr +| 12 = @jsdoc_function_type_expr +| 13 = @jsdoc_optional_type_expr +| 14 = @jsdoc_rest_type_expr +; + +#keyset[id, idx] +jsdoc_record_field_name (int id: @jsdoc_record_type_expr ref, int idx: int ref, varchar(900) name: string ref); +jsdoc_prefix_qualifier (int id: @jsdoc_type_expr ref); +jsdoc_has_new_parameter (int fn: @jsdoc_function_type_expr ref); + +@jsdoc_type_expr_parent = @jsdoc_type_expr | @jsdoc_tag; + +jsdoc_errors (unique int id: @jsdoc_error, int tag: @jsdoc_tag ref, varchar(900) message: string ref, varchar(900) tostring: string ref); + +// YAML +#keyset[parent, idx] +yaml (unique int id: @yaml_node, + int kind: int ref, + int parent: @yaml_node_parent ref, + int idx: int ref, + varchar(900) tag: string ref, + varchar(900) tostring: string ref); + +case @yaml_node.kind of + 0 = @yaml_scalar_node +| 1 = @yaml_mapping_node +| 2 = @yaml_sequence_node +| 3 = @yaml_alias_node +; + +@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node; + +@yaml_node_parent = @yaml_collection_node | @file; + +yaml_anchors (unique int node: @yaml_node ref, + varchar(900) anchor: string ref); + +yaml_aliases (unique int alias: @yaml_alias_node ref, + varchar(900) target: string ref); + +yaml_scalars (unique int scalar: @yaml_scalar_node ref, + int style: int ref, + varchar(900) value: string ref); + +yaml_errors (unique int id: @yaml_error, + varchar(900) message: string ref); + +yaml_locations(unique int locatable: @yaml_locatable ref, + int location: @location_default ref); + +@yaml_locatable = @yaml_node | @yaml_error; + +/* XML Files */ + +xmlEncoding( + unique int id: @file ref, + varchar(900) encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + varchar(900) root: string ref, + varchar(900) publicId: string ref, + varchar(900) systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + varchar(900) name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + varchar(900) name: string ref, + varchar(3600) value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + varchar(900) prefixName: string ref, + varchar(900) URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + varchar(3600) text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + varchar(3600) text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +@dataflownode = @expr | @function_decl_stmt | @class_decl_stmt | @namespace_declaration | @enum_declaration | @property; + +@optionalchainable = @call_expr | @propaccess; + +isOptionalChaining(int id: @optionalchainable ref); + +/* + * configuration files with key value pairs + */ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; + +/** + * The time taken for the extraction of a file. + * This table contains non-deterministic content. + * + * The sum of the `time` column for each (`file`, `timerKind`) pair + * is the total time taken for extraction of `file`. The `extractionPhase` + * column provides a granular view of the extraction time of the file. + */ +extraction_time( + int file : @file ref, + // see `com.semmle.js.extractor.ExtractionMetrics.ExtractionPhase`. + int extractionPhase: int ref, + // 0 for the elapsed CPU time in nanoseconds, 1 for the elapsed wallclock time in nanoseconds + int timerKind: int ref, + float time: float ref +) + +/** + * Non-timing related data for the extraction of a single file. + * This table contains non-deterministic content. + */ +extraction_data( + int file : @file ref, + // the absolute path to the cache file + varchar(900) cacheFile: string ref, + boolean fromCache: boolean ref, + int length: int ref +) diff --git a/javascript/upgrades/930898a4fe07cb48de46800904922ca118b31e50/tuple_type_rest_index.ql b/javascript/upgrades/930898a4fe07cb48de46800904922ca118b31e50/tuple_type_rest_index.ql new file mode 100644 index 00000000000..ff9dcf65489 --- /dev/null +++ b/javascript/upgrades/930898a4fe07cb48de46800904922ca118b31e50/tuple_type_rest_index.ql @@ -0,0 +1,9 @@ +class TupleType extends @tuple_type { + predicate hasChild(int i) { type_child(_, this, i) } + + string toString() { result = "" } +} + +from TupleType tuple, int index +where index = max(int i | tuple.hasChild(i)) +select tuple, index diff --git a/javascript/upgrades/930898a4fe07cb48de46800904922ca118b31e50/upgrade.properties b/javascript/upgrades/930898a4fe07cb48de46800904922ca118b31e50/upgrade.properties new file mode 100644 index 00000000000..9161fbb608f --- /dev/null +++ b/javascript/upgrades/930898a4fe07cb48de46800904922ca118b31e50/upgrade.properties @@ -0,0 +1,4 @@ +description: add support for TypeScript 4.2 +compatibility: backwards +tuple_type_rest_index.rel: run tuple_type_rest_index.qlo +tuple_type_rest.rel: delete diff --git a/python/change-notes/2021-02-12-django-get_redirect_url.md b/python/change-notes/2021-02-12-django-get_redirect_url.md new file mode 100644 index 00000000000..e2aef502c67 --- /dev/null +++ b/python/change-notes/2021-02-12-django-get_redirect_url.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Improved modeling of `django` to recognize request redirects from `get_redirect_url` on a `RedirectView` subclass. diff --git a/python/change-notes/2021-03-01-fluent-interface-data-flow.md b/python/change-notes/2021-03-01-fluent-interface-data-flow.md new file mode 100644 index 00000000000..f1492afcf31 --- /dev/null +++ b/python/change-notes/2021-03-01-fluent-interface-data-flow.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* The data-flow library now recognises more side-effects of method chaining (e.g. `someObject.setX(clean).setY(tainted).setZ...` having a side-effect on `someObject`), as well as other related circumstances where a function input is directly passed to its output. All queries that use data-flow analysis, including most security queries, may return more results accordingly. diff --git a/python/ql/src/semmle/crypto/Crypto.qll b/python/ql/src/semmle/crypto/Crypto.qll index ff13b559198..d9f25b42c9a 100644 --- a/python/ql/src/semmle/crypto/Crypto.qll +++ b/python/ql/src/semmle/crypto/Crypto.qll @@ -1,10 +1,7 @@ /** - * Provides classes for modeling cryptographic libraries. - */ - -/* - * The following information is copied from `/semmlecode-javascript-queries/semmle/javascript/frameworks/CryptoLibraries.qll` - * which should be considered the definitive version (as of Feb 2018) + * Provides classes modeling cryptographic algorithms, separated into strong and weak variants. + * + * The classification into strong and weak are based on Wikipedia, OWASP and google (2017). */ /** @@ -13,6 +10,8 @@ * The names are normalized: upper-case, no spaces, dashes or underscores. * * The names are inspired by the names used in real world crypto libraries. + * + * The classification into strong and weak are based on Wikipedia, OWASP and google (2017). */ private module AlgorithmNames { predicate isStrongHashingAlgorithm(string name) { @@ -81,14 +80,6 @@ private module AlgorithmNames { } predicate isWeakPasswordHashingAlgorithm(string name) { none() } - - /** - * Normalizes `name`: upper-case, no spaces, dashes or underscores. - * - * All names of this module are in this normalized form. - */ - bindingset[name] - string normalizeName(string name) { result = name.toUpperCase().regexpReplaceAll("[-_ ]", "") } } private import AlgorithmNames @@ -121,10 +112,19 @@ abstract class CryptographicAlgorithm extends TCryptographicAlgorithm { string toString() { result = getName() } /** - * Gets the name of the algorithm. + * Gets the normalized name of this algorithm (upper-case, no spaces, dashes or underscores). */ abstract string getName(); + /** + * Holds if the name of this algorithm matches `name` modulo case, + * white space, dashes, and underscores. + */ + bindingset[name] + predicate matchesName(string name) { + name.toUpperCase().regexpReplaceAll("[-_ ]", "") = getName() + } + /** * Holds if this algorithm is weak. */ diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll index 59cc8d529a7..3da77b8ba99 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll @@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep( * Holds if data can flow in one local step from `node1` to `node2`. */ private predicate localFlowStep(Node node1, Node node2, Configuration config) { - simpleLocalFlowStep(node1, node2) and + ( + simpleLocalFlowStep(node1, node2) or + reverseStepThroughInputOutputAlias(node1, node2) + ) and not outBarrier(node1, config) and not inBarrier(node2, config) and not fullBarrier(node1, config) and diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll index 1d2e9052842..54f41545284 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll @@ -415,6 +415,30 @@ private module Cached { store(node1, tc.getContent(), node2, contentType, tc.getContainerType()) } + /** + * Holds if data can flow from `fromNode` to `toNode` because they are the post-update + * nodes of some function output and input respectively, where the output and input + * are aliases. A typical example is a function returning `this`, implementing a fluent + * interface. + */ + cached + predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) { + exists(Node fromPre, Node toPre | + fromPre = fromNode.getPreUpdateNode() and + toPre = toNode.getPreUpdateNode() + | + exists(DataFlowCall c | + // Does the language-specific simpleLocalFlowStep already model flow + // from function input to output? + fromPre = getAnOutNode(c, _) and + toPre.(ArgumentNode).argumentOf(c, _) and + simpleLocalFlowStep(toPre.(ArgumentNode), fromPre) + ) + or + argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre) + ) + } + /** * Holds if the call context `call` either improves virtual dispatch in * `callable` or if it allows us to prune unreachable nodes in `callable`. diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index fb9a77e1adc..9f56bd5a299 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -2074,7 +2074,11 @@ private module Django { // TODO: This doesn't handle attribute assignment. Should be OK, but analysis is not as complete as with // points-to and `.lookup`, which would handle `post = my_post_handler` inside class def result = this.getAMethod() and - result.getName() = HTTP::httpVerbLower() + ( + result.getName() = HTTP::httpVerbLower() + or + result.getName() = "get_redirect_url" + ) } /** @@ -2124,6 +2128,8 @@ private module Django { /** * A function that is a django route handler, meaning it handles incoming requests * with the django framework. + * + * Most functions take a django HttpRequest as a parameter (but not all). */ private class DjangoRouteHandler extends Function { DjangoRouteHandler() { @@ -2132,6 +2138,12 @@ private module Django { any(DjangoViewClass vc).getARequestHandler() = this } + /** + * Gets the index of the parameter where the first routed parameter can be passed -- + * that is, the one just after any possible `self` or HttpRequest parameters. + */ + int getFirstPossibleRoutedParamIndex() { result = 1 + this.getRequestParamIndex() } + /** Gets the index of the request parameter. */ int getRequestParamIndex() { not this.isMethod() and @@ -2145,6 +2157,26 @@ private module Django { Parameter getRequestParam() { result = this.getArg(this.getRequestParamIndex()) } } + /** + * A method named `get_redirect_url` on a django view class. + * + * See https://docs.djangoproject.com/en/3.1/ref/class-based-views/base/#django.views.generic.base.RedirectView.get_redirect_url + * + * Note: this function only does something on a subclass of `RedirectView`, but since + * classes can be considered django view classes without us knowing their super-classes, + * we need to consider _any_ django view class. I don't expect any problems to come from this. + */ + private class GetRedirectUrlFunction extends DjangoRouteHandler { + GetRedirectUrlFunction() { + this.getName() = "get_redirect_url" and + any(DjangoViewClass vc).getARequestHandler() = this + } + + override int getFirstPossibleRoutedParamIndex() { result = 1 } + + override int getRequestParamIndex() { none() } + } + /** A data-flow node that sets up a route on a server, using the django framework. */ abstract private class DjangoRouteSetup extends HTTP::Server::RouteSetup::Range, DataFlow::CfgNode { /** Gets the data-flow node that is used as the argument for the view handler. */ @@ -2175,7 +2207,7 @@ private module Django { // parameter. This should give us more RemoteFlowSources but could also lead to // more FPs. If this turns out to be the wrong tradeoff, we can always change our mind. result in [this.getArg(_), this.getArgByName(_)] and - not result = any(int i | i <= this.getRequestParamIndex() | this.getArg(i)) + not result = any(int i | i < this.getFirstPossibleRoutedParamIndex() | this.getArg(i)) } override string getFramework() { result = "Django" } @@ -2215,7 +2247,8 @@ private module Django { exists(DjangoRouteHandler routeHandler | routeHandler = this.getARequestHandler() | not exists(this.getUrlPattern()) and result in [routeHandler.getArg(_), routeHandler.getArgByName(_)] and - not result = any(int i | i <= routeHandler.getRequestParamIndex() | routeHandler.getArg(i)) + not result = + any(int i | i < routeHandler.getFirstPossibleRoutedParamIndex() | routeHandler.getArg(i)) ) or exists(string name | @@ -2237,7 +2270,8 @@ private module Django { exists(DjangoRouteHandler routeHandler | routeHandler = this.getARequestHandler() | not exists(this.getUrlPattern()) and result in [routeHandler.getArg(_), routeHandler.getArgByName(_)] and - not result = any(int i | i <= routeHandler.getRequestParamIndex() | routeHandler.getArg(i)) + not result = + any(int i | i < routeHandler.getFirstPossibleRoutedParamIndex() | routeHandler.getArg(i)) ) or exists(DjangoRouteHandler routeHandler, DjangoRouteRegex regex | @@ -2249,7 +2283,9 @@ private module Django { not exists(regex.getGroupName(_, _)) and // first group will have group number 1 result = - routeHandler.getArg(routeHandler.getRequestParamIndex() + regex.getGroupNumber(_, _)) + routeHandler + .getArg(routeHandler.getFirstPossibleRoutedParamIndex() - 1 + + regex.getGroupNumber(_, _)) or result = routeHandler.getArgByName(regex.getGroupName(_, _)) ) @@ -2445,4 +2481,31 @@ private module Django { override string getMimetypeDefault() { none() } } + + // --------------------------------------------------------------------------- + // RedirectView handling + // --------------------------------------------------------------------------- + /** + * A return from a method named `get_redirect_url` on a django view class. + * + * Note that in reality, this only does something on a subclass of `RedirectView` -- + * but until API graphs makes this easy to model, I took a shortcut in modeling + * preciseness. + * + * See https://docs.djangoproject.com/en/3.1/ref/class-based-views/base/#redirectview + */ + private class DjangoRedirectViewGetRedirectUrlReturn extends HTTP::Server::HttpRedirectResponse::Range, + DataFlow::CfgNode { + DjangoRedirectViewGetRedirectUrlReturn() { + node = any(GetRedirectUrlFunction f).getAReturnValueFlowNode() + } + + override DataFlow::Node getRedirectLocation() { result = this } + + override DataFlow::Node getBody() { none() } + + override DataFlow::Node getMimetypeOrContentTypeArg() { none() } + + override string getMimetypeDefault() { none() } + } } diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/TestTaint.expected b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/TestTaint.expected index c76685c6739..0602985a392 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/TestTaint.expected +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/TestTaint.expected @@ -1,3 +1,4 @@ +| response_test.py:61 | ok | get_redirect_url | foo | | taint_test.py:8 | ok | test_taint | bar | | taint_test.py:8 | ok | test_taint | foo | | taint_test.py:9 | ok | test_taint | baz | diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v1/response_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/response_test.py similarity index 93% rename from python/ql/test/experimental/library-tests/frameworks/django-v1/response_test.py rename to python/ql/test/experimental/library-tests/frameworks/django-v2-v3/response_test.py index 99dc97624aa..91252378677 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v1/response_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/response_test.py @@ -1,4 +1,5 @@ from django.http.response import HttpResponse, HttpResponseRedirect, HttpResponsePermanentRedirect, JsonResponse, HttpResponseNotFound +from django.views.generic import RedirectView import django.shortcuts # Not an XSS sink, since the Content-Type is not "text/html" @@ -54,6 +55,14 @@ def redirect_shortcut(request): return django.shortcuts.redirect(next) # $ HttpResponse HttpRedirectResponse redirectLocation=next +class CustomRedirectView(RedirectView): + + def get_redirect_url(self, foo): # $ requestHandler routedParameter=foo + ensure_tainted(foo) + next = "https://example.com/{}".format(foo) + return next # $ HttpResponse HttpRedirectResponse redirectLocation=next + + # Ensure that simple subclasses are still vuln to XSS def xss__not_found(request): return HttpResponseNotFound(request.GET.get("name")) # $HttpResponse mimetype=text/html responseBody=Attribute() diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/urls.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/urls.py index 0f5c360b9d8..2f0d978c97a 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/urls.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/urls.py @@ -15,4 +15,7 @@ urlpatterns = [ path("basic-view-handler/", views.MyBasicViewHandler.as_view()), # $routeSetup="basic-view-handler/" path("custom-inheritance-view-handler/", views.MyViewHandlerWithCustomInheritance.as_view()), # $routeSetup="custom-inheritance-view-handler/" + + path("CustomRedirectView/", views.CustomRedirectView.as_view()), # $routeSetup="CustomRedirectView/" + path("CustomRedirectView2/", views.CustomRedirectView2.as_view()), # $routeSetup="CustomRedirectView2/" ] diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py index d2028d0dd03..2a3ed803507 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py @@ -1,5 +1,5 @@ from django.http import HttpRequest, HttpResponse -from django.views import View +from django.views.generic import View, RedirectView from django.views.decorators.csrf import csrf_exempt @@ -32,3 +32,16 @@ class MyViewHandlerWithCustomInheritance(MyCustomViewBaseClass): def get(self, request: HttpRequest): # $ requestHandler print(self.request.GET) return HttpResponse("MyViewHandlerWithCustomInheritance: GET") # $ HttpResponse + +# RedirectView +# See docs at https://docs.djangoproject.com/en/3.1/ref/class-based-views/base/#redirectview +class CustomRedirectView(RedirectView): + + def get_redirect_url(self, foo): # $ requestHandler routedParameter=foo + next = "https://example.com/{}".format(foo) + return next # $ HttpResponse HttpRedirectResponse redirectLocation=next + + +class CustomRedirectView2(RedirectView): + + url = "https://example.com/%(foo)s"